dep3-0.2.1/.cargo_vcs_info.json0000644000000001420000000000100116640ustar { "git": { "sha1": "fa493d03c4c86016ca41c361d70504155f7f13a2" }, "path_in_vcs": "dep3" }dep3-0.2.1/.gitignore000064400000000000000000000000101046102023000124360ustar 00000000000000/target dep3-0.2.1/Cargo.lock0000644000000430530000000000100076470ustar # This file is automatically @generated by Cargo. # It is not intended for manual editing. version = 4 [[package]] name = "aho-corasick" version = "1.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ddd31a130427c27518df266943a5308ed92d4b226cc639f5a8f1002816174301" dependencies = [ "memchr", ] [[package]] name = "android_system_properties" version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311" dependencies = [ "libc", ] [[package]] name = "autocfg" version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8" [[package]] name = "bumpalo" version = "3.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "46c5e41b57b8bba42a04676d81cb89e9ee8e859a1a66f80a5a72e1cb76b34d43" [[package]] name = "cc" version = "1.2.48" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c481bdbf0ed3b892f6f806287d72acd515b352a4ec27a208489b8c1bc839633a" dependencies = [ "find-msvc-tools", "shlex", ] [[package]] name = "cfg-if" version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801" [[package]] name = "chrono" version = "0.4.42" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "145052bdd345b87320e369255277e3fb5152762ad123a901ef5c262dd38fe8d2" dependencies = [ "iana-time-zone", "js-sys", "num-traits", "wasm-bindgen", "windows-link", ] [[package]] name = "core-foundation-sys" version = "0.8.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" [[package]] name = "countme" version = "3.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7704b5fdd17b18ae31c4c1da5a2e0305a2bf17b5249300a9ee9ed7b72114c636" [[package]] name = "deb822-derive" version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "86bf2d0fa4ce2457e94bd7efb15aeadc115297f04b660bd0da706729e0d91442" dependencies = [ "proc-macro2", "quote", "syn", ] [[package]] name = "deb822-fast" version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f410ccb5cbd9b81d56b290131bad4350ecf8b46416fb901e759dc1e6916a8198" dependencies = [ "deb822-derive", ] [[package]] name = "deb822-lossless" version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cdcadf12851ddb37dc938e724beeb50e83bfe1a1fda3c15b997dc1105ec49e3d" dependencies = [ "regex", "rowan", "serde", ] [[package]] name = "dep3" version = "0.2.1" dependencies = [ "chrono", "deb822-fast", "deb822-lossless", "url", ] [[package]] name = "displaydoc" version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0" dependencies = [ "proc-macro2", "quote", "syn", ] [[package]] name = "find-msvc-tools" version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3a3076410a55c90011c298b04d0cfa770b00fa04e1e3c97d3f6c9de105a03844" [[package]] name = "form_urlencoded" version = "1.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cb4cb245038516f5f85277875cdaa4f7d2c9a0fa0468de06ed190163b1581fcf" dependencies = [ "percent-encoding", ] [[package]] name = "hashbrown" version = "0.14.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" [[package]] name = "iana-time-zone" version = "0.1.64" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "33e57f83510bb73707521ebaffa789ec8caf86f9657cad665b092b581d40e9fb" dependencies = [ "android_system_properties", "core-foundation-sys", "iana-time-zone-haiku", "js-sys", "log", "wasm-bindgen", "windows-core", ] [[package]] name = "iana-time-zone-haiku" version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f31827a206f56af32e590ba56d5d2d085f558508192593743f16b2306495269f" dependencies = [ "cc", ] [[package]] name = "icu_collections" version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4c6b649701667bbe825c3b7e6388cb521c23d88644678e83c0c4d0a621a34b43" dependencies = [ "displaydoc", "potential_utf", "yoke", "zerofrom", "zerovec", ] [[package]] name = "icu_locale_core" version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "edba7861004dd3714265b4db54a3c390e880ab658fec5f7db895fae2046b5bb6" dependencies = [ "displaydoc", "litemap", "tinystr", "writeable", "zerovec", ] [[package]] name = "icu_normalizer" version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5f6c8828b67bf8908d82127b2054ea1b4427ff0230ee9141c54251934ab1b599" dependencies = [ "icu_collections", "icu_normalizer_data", "icu_properties", "icu_provider", "smallvec", "zerovec", ] [[package]] name = "icu_normalizer_data" version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7aedcccd01fc5fe81e6b489c15b247b8b0690feb23304303a9e560f37efc560a" [[package]] name = "icu_properties" version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e93fcd3157766c0c8da2f8cff6ce651a31f0810eaa1c51ec363ef790bbb5fb99" dependencies = [ "icu_collections", "icu_locale_core", "icu_properties_data", "icu_provider", "zerotrie", "zerovec", ] [[package]] name = "icu_properties_data" version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "02845b3647bb045f1100ecd6480ff52f34c35f82d9880e029d329c21d1054899" [[package]] name = "icu_provider" version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "85962cf0ce02e1e0a629cc34e7ca3e373ce20dda4c4d7294bbd0bf1fdb59e614" dependencies = [ "displaydoc", "icu_locale_core", "writeable", "yoke", "zerofrom", "zerotrie", "zerovec", ] [[package]] name = "idna" version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3b0875f23caa03898994f6ddc501886a45c7d3d62d04d2d90788d47be1b1e4de" dependencies = [ "idna_adapter", "smallvec", "utf8_iter", ] [[package]] name = "idna_adapter" version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3acae9609540aa318d1bc588455225fb2085b9ed0c4f6bd0d9d5bcd86f1a0344" dependencies = [ "icu_normalizer", "icu_properties", ] [[package]] name = "js-sys" version = "0.3.83" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "464a3709c7f55f1f721e5389aa6ea4e3bc6aba669353300af094b29ffbdde1d8" dependencies = [ "once_cell", "wasm-bindgen", ] [[package]] name = "libc" version = "0.2.178" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "37c93d8daa9d8a012fd8ab92f088405fb202ea0b6ab73ee2482ae66af4f42091" [[package]] name = "litemap" version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6373607a59f0be73a39b6fe456b8192fcc3585f602af20751600e974dd455e77" [[package]] name = "log" version = "0.4.28" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "34080505efa8e45a4b816c349525ebe327ceaa8559756f0356cba97ef3bf7432" [[package]] name = "memchr" version = "2.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f52b00d39961fc5b2736ea853c9cc86238e165017a493d1d5c8eac6bdc4cc273" [[package]] name = "num-traits" version = "0.2.19" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" dependencies = [ "autocfg", ] [[package]] name = "once_cell" version = "1.21.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d" [[package]] name = "percent-encoding" version = "2.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9b4f627cb1b25917193a259e49bdad08f671f8d9708acfd5fe0a8c1455d87220" [[package]] name = "potential_utf" version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b73949432f5e2a09657003c25bca5e19a0e9c84f8058ca374f49e0ebe605af77" dependencies = [ "zerovec", ] [[package]] name = "proc-macro2" version = "1.0.103" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5ee95bc4ef87b8d5ba32e8b7714ccc834865276eab0aed5c9958d00ec45f49e8" dependencies = [ "unicode-ident", ] [[package]] name = "quote" version = "1.0.42" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a338cc41d27e6cc6dce6cefc13a0729dfbb81c262b1f519331575dd80ef3067f" dependencies = [ "proc-macro2", ] [[package]] name = "regex" version = "1.12.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "843bc0191f75f3e22651ae5f1e72939ab2f72a4bc30fa80a066bd66edefc24d4" dependencies = [ "aho-corasick", "memchr", "regex-automata", "regex-syntax", ] [[package]] name = "regex-automata" version = "0.4.13" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5276caf25ac86c8d810222b3dbb938e512c55c6831a10f3e6ed1c93b84041f1c" dependencies = [ "aho-corasick", "memchr", "regex-syntax", ] [[package]] name = "regex-syntax" version = "0.8.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7a2d987857b319362043e95f5353c0535c1f58eec5336fdfcf626430af7def58" [[package]] name = "rowan" version = "0.16.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "417a3a9f582e349834051b8a10c8d71ca88da4211e4093528e36b9845f6b5f21" dependencies = [ "countme", "hashbrown", "rustc-hash", "text-size", ] [[package]] name = "rustc-hash" version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" [[package]] name = "rustversion" version = "1.0.22" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b39cdef0fa800fc44525c84ccb54a029961a8215f9619753635a9c0d2538d46d" [[package]] name = "serde" version = "1.0.228" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9a8e94ea7f378bd32cbbd37198a4a91436180c5bb472411e48b5ec2e2124ae9e" dependencies = [ "serde_core", "serde_derive", ] [[package]] name = "serde_core" version = "1.0.228" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "41d385c7d4ca58e59fc732af25c3983b67ac852c1a25000afe1175de458b67ad" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" version = "1.0.228" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79" dependencies = [ "proc-macro2", "quote", "syn", ] [[package]] name = "shlex" version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" [[package]] name = "smallvec" version = "1.15.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "67b1b7a3b5fe4f1376887184045fcf45c69e92af734b7aaddc05fb777b6fbd03" [[package]] name = "stable_deref_trait" version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6ce2be8dc25455e1f91df71bfa12ad37d7af1092ae736f3a6cd0e37bc7810596" [[package]] name = "syn" version = "2.0.111" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "390cc9a294ab71bdb1aa2e99d13be9c753cd2d7bd6560c77118597410c4d2e87" dependencies = [ "proc-macro2", "quote", "unicode-ident", ] [[package]] name = "synstructure" version = "0.13.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "728a70f3dbaf5bab7f0c4b1ac8d7ae5ea60a4b5549c8a5914361c99147a709d2" dependencies = [ "proc-macro2", "quote", "syn", ] [[package]] name = "text-size" version = "1.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f18aa187839b2bdb1ad2fa35ead8c4c2976b64e4363c386d45ac0f7ee85c9233" [[package]] name = "tinystr" version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "42d3e9c45c09de15d06dd8acf5f4e0e399e85927b7f00711024eb7ae10fa4869" dependencies = [ "displaydoc", "zerovec", ] [[package]] name = "unicode-ident" version = "1.0.22" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9312f7c4f6ff9069b165498234ce8be658059c6728633667c526e27dc2cf1df5" [[package]] name = "url" version = "2.5.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "08bc136a29a3d1758e07a9cca267be308aeebf5cfd5a10f3f67ab2097683ef5b" dependencies = [ "form_urlencoded", "idna", "percent-encoding", "serde", ] [[package]] name = "utf8_iter" version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b6c140620e7ffbb22c2dee59cafe6084a59b5ffc27a8859a5f0d494b5d52b6be" [[package]] name = "wasm-bindgen" version = "0.2.106" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0d759f433fa64a2d763d1340820e46e111a7a5ab75f993d1852d70b03dbb80fd" dependencies = [ "cfg-if", "once_cell", "rustversion", "wasm-bindgen-macro", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-macro" version = "0.2.106" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "48cb0d2638f8baedbc542ed444afc0644a29166f1595371af4fecf8ce1e7eeb3" dependencies = [ "quote", "wasm-bindgen-macro-support", ] [[package]] name = "wasm-bindgen-macro-support" version = "0.2.106" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cefb59d5cd5f92d9dcf80e4683949f15ca4b511f4ac0a6e14d4e1ac60c6ecd40" dependencies = [ "bumpalo", "proc-macro2", "quote", "syn", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-shared" version = "0.2.106" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cbc538057e648b67f72a982e708d485b2efa771e1ac05fec311f9f63e5800db4" dependencies = [ "unicode-ident", ] [[package]] name = "windows-core" version = "0.62.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b8e83a14d34d0623b51dce9581199302a221863196a1dde71a7663a4c2be9deb" dependencies = [ "windows-implement", "windows-interface", "windows-link", "windows-result", "windows-strings", ] [[package]] name = "windows-implement" version = "0.60.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "053e2e040ab57b9dc951b72c264860db7eb3b0200ba345b4e4c3b14f67855ddf" dependencies = [ "proc-macro2", "quote", "syn", ] [[package]] name = "windows-interface" version = "0.59.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3f316c4a2570ba26bbec722032c4099d8c8bc095efccdc15688708623367e358" dependencies = [ "proc-macro2", "quote", "syn", ] [[package]] name = "windows-link" version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5" [[package]] name = "windows-result" version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7781fa89eaf60850ac3d2da7af8e5242a5ea78d1a11c49bf2910bb5a73853eb5" dependencies = [ "windows-link", ] [[package]] name = "windows-strings" version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7837d08f69c77cf6b07689544538e017c1bfcf57e34b4c0ff58e6c2cd3b37091" dependencies = [ "windows-link", ] [[package]] name = "writeable" version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9edde0db4769d2dc68579893f2306b26c6ecfbe0ef499b013d731b7b9247e0b9" [[package]] name = "yoke" version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "72d6e5c6afb84d73944e5cedb052c4680d5657337201555f9f2a16b7406d4954" dependencies = [ "stable_deref_trait", "yoke-derive", "zerofrom", ] [[package]] name = "yoke-derive" version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b659052874eb698efe5b9e8cf382204678a0086ebf46982b79d6ca3182927e5d" dependencies = [ "proc-macro2", "quote", "syn", "synstructure", ] [[package]] name = "zerofrom" version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "50cc42e0333e05660c3587f3bf9d0478688e15d870fab3346451ce7f8c9fbea5" dependencies = [ "zerofrom-derive", ] [[package]] name = "zerofrom-derive" version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d71e5d6e06ab090c67b5e44993ec16b72dcbaabc526db883a360057678b48502" dependencies = [ "proc-macro2", "quote", "syn", "synstructure", ] [[package]] name = "zerotrie" version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2a59c17a5562d507e4b54960e8569ebee33bee890c70aa3fe7b97e85a9fd7851" dependencies = [ "displaydoc", "yoke", "zerofrom", ] [[package]] name = "zerovec" version = "0.11.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6c28719294829477f525be0186d13efa9a3c602f7ec202ca9e353d310fb9a002" dependencies = [ "yoke", "zerofrom", "zerovec-derive", ] [[package]] name = "zerovec-derive" version = "0.11.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "eadce39539ca5cb3985590102671f2567e659fca9666581ad3411d59207951f3" dependencies = [ "proc-macro2", "quote", "syn", ] dep3-0.2.1/Cargo.toml0000644000000026220000000000100076670ustar # THIS FILE IS AUTOMATICALLY GENERATED BY CARGO # # When uploading crates to the registry Cargo will automatically # "normalize" Cargo.toml files for maximal compatibility # with all versions of Cargo and also rewrite `path` dependencies # to registry (e.g., crates.io) dependencies. # # If you are reading this file be aware that the original Cargo.toml # will likely look very different (and much more reasonable). # See Cargo.toml.orig for the original contents. [package] edition = "2021" name = "dep3" version = "0.2.1" build = false autolib = false autobins = false autoexamples = false autotests = false autobenches = false description = "A library for parsing and generating DEP-3 headers." homepage = "https://github.com/jelmer/deb822-lossless" readme = "README.md" keywords = [ "debian", "patch", "dep3", "lossless", ] categories = ["parser-implementations"] license = "Apache-2.0" repository = "https://github.com/jelmer/deb822-lossless" [badges.maintenance] status = "actively-maintained" [features] default = ["lossless"] lossless = ["dep:deb822-lossless"] [lib] name = "dep3" path = "src/lib.rs" [[example]] name = "read-dep3" path = "examples/read-dep3.rs" [dependencies.chrono] version = ">=0.4, <0.5" [dependencies.deb822-fast] version = ">=0.1, <0.3" features = ["derive"] [dependencies.deb822-lossless] version = ">=0.2, <0.6" optional = true [dependencies.url] version = ">=2, <3" dep3-0.2.1/Cargo.toml.orig000064400000000000000000000013171046102023000133500ustar 00000000000000[package] name = "dep3" edition = "2021" license = "Apache-2.0" version = "0.2.1" description = "A library for parsing and generating DEP-3 headers." homepage = "https://github.com/jelmer/deb822-lossless" repository = "https://github.com/jelmer/deb822-lossless" keywords = ["debian", "patch", "dep3", "lossless"] categories = ["parser-implementations"] [dependencies] chrono = ">=0.4, <0.5" deb822-lossless = { path = "../deb822-lossless", version = ">=0.2, <0.6", optional = true } deb822-fast = { path = "../deb822-fast", version = ">=0.1, <0.3", features = ["derive"] } url = ">=2, <3" [features] default = ["lossless"] lossless = ["dep:deb822-lossless"] [badges] maintenance = { status = "actively-maintained" } dep3-0.2.1/README.md000064400000000000000000000013071046102023000117370ustar 00000000000000Rust parser for Debian DEP-3 patch headers ------------------------------------------ # Examples ```rust use dep3::PatchHeader; use std::str::FromStr; let text = r#"From: John Doe Date: Mon, 1 Jan 2000 00:00:00 +0000 Subject: [PATCH] fix a bug Bug-Debian: https://bugs.debian.org/123456 Bug: https://bugzilla.example.com/bug.cgi?id=123456 Forwarded: not-needed "#; let patch_header = PatchHeader::from_str(text).unwrap(); assert_eq!(patch_header.description(), Some("[PATCH] fix a bug".to_string())); assert_eq!(patch_header.vendor_bugs("Debian").collect::>(), vec!["https://bugs.debian.org/123456".to_string()]); ``` See for details dep3-0.2.1/disperse.conf000064400000000000000000000000461046102023000131440ustar 00000000000000timeout_days: 5 tag_name: "v$VERSION" dep3-0.2.1/examples/read-dep3.rs000064400000000000000000000014021046102023000144040ustar 00000000000000use dep3::lossy::PatchHeader; use std::str::FromStr; pub const TEXT: &str = r#"From: John Doe Date: Mon, 1 Jan 2000 00:00:00 +0000 Subject: [PATCH] fix a bug Bug-Debian: https://bugs.debian.org/123456 Bug: https://bugzilla.example.com/bug.cgi?id=123456 Forwarded: not-needed "#; pub fn main() { let patch_header = match PatchHeader::from_str(TEXT) { Ok(header) => header, Err(e) => { eprintln!("Failed to parse patch header: {}", e); std::process::exit(1); } }; if let Some(description) = &patch_header.description { println!("Description: {}", description); } if let Some(bug_debian) = &patch_header.bug_debian { println!("Debian Bugs: {}", bug_debian); } } dep3-0.2.1/src/fields.rs000064400000000000000000000133071046102023000130660ustar 00000000000000use std::borrow::Cow; /// Whether the patch has been forwarded to the upstream project. #[derive(Debug, PartialEq, Eq, Clone)] pub enum Forwarded { /// The patch has not been forwarded to the upstream project. No, /// The patch does not need to be forwarded to the upstream project. NotNeeded, /// The patch has been forwarded to the upstream project, and the value /// provides some reference to the forwarded patch. Yes(Cow<'static, str>), } impl std::fmt::Display for Forwarded { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { match self { Forwarded::No => f.write_str("no"), Forwarded::NotNeeded => f.write_str("not-needed"), Forwarded::Yes(s) => f.write_str(s), } } } impl std::str::FromStr for Forwarded { type Err = &'static str; fn from_str(s: &str) -> Result { match s { "no" => Ok(Forwarded::No), "not-needed" => Ok(Forwarded::NotNeeded), s => Ok(Forwarded::Yes(Cow::Owned(s.to_string()))), } } } /// The category of the origin #[derive(Debug, PartialEq, Eq, Clone, Copy)] pub enum OriginCategory { /// an upstream patch that had to be modified to apply on the current version Backport, /// a patch created by Debian or another distribution vendor Vendor, /// a patch cherry-picked from the upstream VCS Upstream, /// a patch that does not fit in any of the above categories Other, } impl std::fmt::Display for OriginCategory { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { match self { OriginCategory::Backport => f.write_str("backport"), OriginCategory::Vendor => f.write_str("vendor"), OriginCategory::Upstream => f.write_str("upstream"), OriginCategory::Other => f.write_str("other"), } } } impl std::str::FromStr for OriginCategory { type Err = &'static str; fn from_str(s: &str) -> Result { match s { "backport" => Ok(OriginCategory::Backport), "vendor" => Ok(OriginCategory::Vendor), "upstream" => Ok(OriginCategory::Upstream), "other" => Ok(OriginCategory::Other), _ => Err("invalid origin category"), } } } /// The origin of the patch #[derive(Debug, PartialEq, Eq, Clone)] pub enum Origin { /// The patch was cherry-picked from the upstream VCS Commit(Cow<'static, str>), /// Some other origin Other(Cow<'static, str>), } impl std::fmt::Display for Origin { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { match self { Origin::Commit(s) => write!(f, "commit:{}", s), Origin::Other(s) => f.write_str(s), } } } impl std::str::FromStr for Origin { type Err = &'static str; fn from_str(s: &str) -> Result { if let Some(rest) = s.strip_prefix("commit:") { Ok(Origin::Commit(Cow::Owned(rest.to_string()))) } else { Ok(Origin::Other(Cow::Owned(s.to_string()))) } } } /// Whether the patch has been applied in the upstream project. #[derive(Debug, PartialEq, Eq, Clone)] pub enum AppliedUpstream { /// The patch has not been applied in the upstream project, in the specified commit. Commit(Cow<'static, str>), /// The patch has been applied in the upstream project, in the specified reference. Other(Cow<'static, str>), } impl std::fmt::Display for AppliedUpstream { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { match self { AppliedUpstream::Commit(s) => write!(f, "commit:{}", s), AppliedUpstream::Other(s) => f.write_str(s), } } } impl std::str::FromStr for AppliedUpstream { type Err = &'static str; fn from_str(s: &str) -> Result { if let Some(rest) = s.strip_prefix("commit:") { Ok(AppliedUpstream::Commit(Cow::Owned(rest.to_string()))) } else { Ok(AppliedUpstream::Other(Cow::Owned(s.to_string()))) } } } pub(crate) fn parse_origin(s: &str) -> (Option, Origin) { // if origin starts with ", " then it is a category let mut parts = s.splitn(2, ", "); let (category, s) = match parts.next() { Some("backport") => (Some(OriginCategory::Backport), parts.next().unwrap_or("")), Some("vendor") => (Some(OriginCategory::Vendor), parts.next().unwrap_or("")), Some("upstream") => (Some(OriginCategory::Upstream), parts.next().unwrap_or("")), Some("other") => (Some(OriginCategory::Other), parts.next().unwrap_or("")), None | Some(_) => (None, s), }; if let Some(rest) = s.strip_prefix("commit:") { (category, Origin::Commit(Cow::Owned(rest.to_string()))) } else { (category, Origin::Other(Cow::Owned(s.to_string()))) } } pub(crate) fn format_origin(category: &Option, origin: &Origin) -> String { format!( "{}{}", category.map(|c| c.to_string() + ", ").unwrap_or_default(), origin ) } #[cfg(test)] mod tests { use super::*; #[test] fn test_forwarded_display() { assert_eq!(Forwarded::No.to_string(), "no"); assert_eq!(Forwarded::Yes(Cow::Borrowed("url")).to_string(), "url"); assert_eq!(Forwarded::NotNeeded.to_string(), "not-needed"); } #[test] fn test_applied_upstream_display() { let commit = AppliedUpstream::Commit(Cow::Borrowed("abc123")); assert_eq!(commit.to_string(), "commit:abc123"); let other = AppliedUpstream::Other(Cow::Borrowed("merged")); assert_eq!(other.to_string(), "merged"); } } dep3-0.2.1/src/lib.rs000064400000000000000000000014441046102023000123650ustar 00000000000000#![deny(missing_docs)] //! A library for parsing and generating Debian patch headers. //! //! # Examples //! //! ```rust //! use dep3::PatchHeader; //! use std::str::FromStr; //! let text = r#"From: John Doe //! Date: Mon, 1 Jan 2000 00:00:00 +0000 //! Subject: [PATCH] fix a bug //! Bug-Debian: https://bugs.debian.org/123456 //! Bug: https://bugzilla.example.com/bug.cgi?id=123456 //! Forwarded: not-needed //! "#; //! //! let patch_header = PatchHeader::from_str(text).unwrap(); //! assert_eq!(patch_header.description, Some("[PATCH] fix a bug".to_string())); //! assert_eq!(patch_header.vendor_bugs("Debian"), Some("https://bugs.debian.org/123456")); //! ``` mod fields; pub use fields::*; #[cfg(feature = "lossless")] pub mod lossless; pub mod lossy; pub use lossy::PatchHeader; dep3-0.2.1/src/lossless.rs000064400000000000000000000347541046102023000135000ustar 00000000000000//! A library for parsing and generating Debian patch headers. //! //! # Examples //! //! ```rust //! use dep3::lossless::PatchHeader; //! use std::str::FromStr; //! let text = r#"From: John Doe //! Date: Mon, 1 Jan 2000 00:00:00 +0000 //! Subject: [PATCH] fix a bug //! Bug-Debian: https://bugs.debian.org/123456 //! Bug: https://bugzilla.example.com/bug.cgi?id=123456 //! Forwarded: not-needed //! "#; //! //! let patch_header = PatchHeader::from_str(text).unwrap(); //! assert_eq!(patch_header.description(), Some("[PATCH] fix a bug".to_string())); //! assert_eq!(patch_header.vendor_bugs("Debian").collect::>(), vec!["https://bugs.debian.org/123456".to_string()]); //! ``` use deb822_lossless::Paragraph; use crate::fields::*; /// A Debian patch header. pub struct PatchHeader(Paragraph); impl PatchHeader { /// Create a new, empty patch header. pub fn new() -> Self { PatchHeader(Paragraph::new()) } /// Get a reference to the underlying `Paragraph`. pub fn as_deb822(&self) -> &Paragraph { &self.0 } /// Get a mutable reference to the underlying `Paragraph`, mutably. pub fn as_deb822_mut(&mut self) -> &mut Paragraph { &mut self.0 } /// The origin of the patch. pub fn origin(&self) -> Option<(Option, Origin)> { self.0 .get("Origin") .as_deref() .map(crate::fields::parse_origin) } /// Set the origin of the patch. pub fn set_origin(&mut self, category: Option, origin: Origin) { self.0.insert( "Origin", crate::fields::format_origin(&category, &origin).as_str(), ); } /// The `Forwarded` field. pub fn forwarded(&self) -> Option { self.0 .get("Forwarded") .as_deref() .map(|s| s.parse().unwrap()) } /// Set the `Forwarded` field. pub fn set_forwarded(&mut self, forwarded: Forwarded) { self.0.insert("Forwarded", forwarded.to_string().as_str()); } /// The author of the patch. pub fn author(&self) -> Option { self.0.get("Author").or_else(|| self.0.get("From")) } /// Set the author of the patch. pub fn set_author(&mut self, author: &str) { if self.0.contains_key("From") { self.0.insert("From", author); } else { self.0.insert("Author", author); } } /// The `Reviewed-By` field. pub fn reviewed_by(&self) -> Vec { self.0.get_all("Reviewed-By").collect() } /// Get the last update date of the patch. pub fn last_update(&self) -> Option { self.0 .get("Last-Update") .as_deref() .and_then(|s| chrono::NaiveDate::parse_from_str(s, "%Y-%m-%d").ok()) } /// Set the date of the last update pub fn set_last_update(&mut self, date: chrono::NaiveDate) { self.0 .insert("Last-Update", date.format("%Y-%m-%d").to_string().as_str()); } /// The `Applied-Upstream` field. pub fn applied_upstream(&self) -> Option { self.0 .get("Applied-Upstream") .as_deref() .map(|s| s.parse().unwrap()) } /// Set the `Applied-Upstream` field. pub fn set_applied_upstream(&mut self, applied_upstream: AppliedUpstream) { self.0 .insert("Applied-Upstream", applied_upstream.to_string().as_str()); } /// Get the bugs associated with the patch. pub fn bugs(&self) -> impl Iterator, String)> + '_ { self.0.items().filter_map(|(k, v)| { if k.starts_with("Bug-") { Some((Some(k.strip_prefix("Bug-").unwrap().to_string()), v)) } else if k == "Bug" { Some((None, v)) } else { None } }) } /// Get the bugs associated with a specific vendor. pub fn vendor_bugs<'a>(&'a self, vendor: &'a str) -> impl Iterator + 'a { self.bugs().filter_map(|(k, v)| { if k == Some(vendor.to_string()) { Some(v) } else { None } }) } /// Set the upstream bug associated with the patch. pub fn set_upstream_bug(&mut self, bug: &str) { self.0.insert("Bug", bug); } /// Set the bug associated with a specific vendor. pub fn set_vendor_bug(&mut self, vendor: &str, bug: &str) { self.0.insert(format!("Bug-{}", vendor).as_str(), bug); } /// Get the description or subject field. fn description_field(&self) -> Option { self.0.get("Description").or_else(|| self.0.get("Subject")) } /// Get the description of the patch. pub fn description(&self) -> Option { self.description_field() .as_deref() .map(|s| s.split('\n').next().unwrap_or(s).to_string()) } /// Set the description of the patch. pub fn set_description(&mut self, description: &str) { if let Some(subject) = self.0.get("Subject") { // Replace the first line with ours let new = format!( "{}\n{}", description, subject.split_once('\n').map(|x| x.1).unwrap_or("") ); self.0.insert("Subject", new.as_str()); } else if let Some(description) = self.0.get("Description") { // Replace the first line with ours let new = format!( "{}\n{}", description.split_once('\n').map(|x| x.1).unwrap_or(""), description ); self.0.insert("Description", new.as_str()); } else { self.0.insert("Description", description); } } /// Get the long description of the patch. pub fn long_description(&self) -> Option { self.description_field() .as_deref() .map(|s| s.split_once('\n').map(|x| x.1).unwrap_or("").to_string()) } /// Set the long description of the patch. pub fn set_long_description(&mut self, long_description: &str) { if let Some(subject) = self.0.get("Subject") { // Keep the first line, but replace the rest with our text let first_line = subject .split_once('\n') .map(|x| x.0) .unwrap_or(subject.as_str()); let new = format!("{}\n{}", first_line, long_description); self.0.insert("Subject", new.as_str()); } else if let Some(description) = self.0.get("Description") { // Keep the first line, but replace the rest with our text let first_line = description .split_once('\n') .map(|x| x.0) .unwrap_or(description.as_str()); let new = format!("{}\n{}", first_line, long_description); self.0.insert("Description", new.as_str()); } else { self.0.insert("Description", long_description); } } /// Write the patch header pub fn write(&self, writer: &mut W) -> std::io::Result<()> { writer.write_all(self.to_string().as_bytes()) } } impl std::fmt::Display for PatchHeader { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { f.write_str(&self.0.to_string()) } } impl Default for PatchHeader { fn default() -> Self { Self::new() } } impl std::str::FromStr for PatchHeader { type Err = deb822_lossless::ParseError; fn from_str(s: &str) -> Result { Ok(PatchHeader(Paragraph::from_str(s)?)) } } #[cfg(test)] mod tests { use super::PatchHeader; use std::borrow::Cow; use std::str::FromStr; #[test] fn test_upstream() { let text = r#"From: Ulrich Drepper Subject: Fix regex problems with some multi-bytes characters . * posix/bug-regex17.c: Add testcases. * posix/regcomp.c (re_compile_fastmap_iter): Rewrite COMPLEX_BRACKET handling. . Origin: upstream, http://sourceware.org/git/?p=glibc.git;a=commitdiff;h=bdb56bac Bug: http://sourceware.org/bugzilla/show_bug.cgi?id=9697 Bug-Debian: http://bugs.debian.org/510219 "#; let header = PatchHeader::from_str(text).unwrap(); assert_eq!( header.origin(), Some(( Some(super::OriginCategory::Upstream), super::Origin::Other(Cow::Borrowed( "http://sourceware.org/git/?p=glibc.git;a=commitdiff;h=bdb56bac" )) )) ); assert_eq!(header.forwarded(), None); assert_eq!( header.author(), Some("Ulrich Drepper ".to_string()) ); assert_eq!(header.reviewed_by(), Vec::<&str>::new()); assert_eq!(header.last_update(), None); assert_eq!(header.applied_upstream(), None); assert_eq!( header.bugs().collect::>(), vec![ ( None, "http://sourceware.org/bugzilla/show_bug.cgi?id=9697".to_string() ), ( Some("Debian".to_string()), "http://bugs.debian.org/510219".to_string() ), ] ); assert_eq!( header.description(), Some("Fix regex problems with some multi-bytes characters".to_string()) ); } #[test] fn test_forwarded() { let text = r#"Description: Use FHS compliant paths by default Upstream is not interested in switching to those paths. . But we will continue using them in Debian nevertheless to comply with our policy. Forwarded: http://lists.example.com/oct-2006/1234.html Author: John Doe Last-Update: 2006-12-21 "#; let header = PatchHeader::from_str(text).unwrap(); assert_eq!(header.origin(), None); assert_eq!( header.forwarded(), Some(super::Forwarded::Yes(Cow::Borrowed( "http://lists.example.com/oct-2006/1234.html" ))) ); assert_eq!( header.author(), Some("John Doe ".to_string()) ); assert_eq!(header.reviewed_by(), Vec::<&str>::new()); assert_eq!( header.last_update(), Some(chrono::NaiveDate::from_ymd_opt(2006, 12, 21).unwrap()) ); assert_eq!(header.applied_upstream(), None); assert_eq!(header.bugs().collect::>(), vec![]); assert_eq!( header.description(), Some("Use FHS compliant paths by default".to_string()) ); } #[test] fn test_not_forwarded() { let text = r#"Description: Workaround for broken symbol resolving on mips/mipsel The correct fix will be done in etch and it will require toolchain fixes. Forwarded: not-needed Origin: vendor, http://bugs.debian.org/cgi-bin/bugreport.cgi?msg=80;bug=265678 Bug-Debian: http://bugs.debian.org/265678 Author: Thiemo Seufer "#; let header = PatchHeader::from_str(text).unwrap(); assert_eq!( header.origin(), Some(( Some(super::OriginCategory::Vendor), super::Origin::Other(Cow::Borrowed( "http://bugs.debian.org/cgi-bin/bugreport.cgi?msg=80;bug=265678" )) )) ); assert_eq!(header.forwarded(), Some(super::Forwarded::NotNeeded)); assert_eq!( header.author(), Some("Thiemo Seufer ".to_string()) ); assert_eq!(header.reviewed_by(), Vec::<&str>::new()); assert_eq!(header.last_update(), None); assert_eq!(header.applied_upstream(), None); assert_eq!( header.bugs().collect::>(), vec![( Some("Debian".to_string()), "http://bugs.debian.org/265678".to_string() ),] ); assert_eq!( header.description(), Some("Workaround for broken symbol resolving on mips/mipsel".to_string()) ); } #[test] fn test_applied_upstream() { let text = r#"Description: Fix widget frobnication speeds Frobnicating widgets too quickly tended to cause explosions. Forwarded: http://lists.example.com/2010/03/1234.html Author: John Doe Applied-Upstream: 1.2, http://bzr.example.com/frobnicator/trunk/revision/123 Last-Update: 2010-03-29 "#; let header = PatchHeader::from_str(text).unwrap(); assert_eq!(header.origin(), None); assert_eq!( header.forwarded(), Some(super::Forwarded::Yes(Cow::Borrowed( "http://lists.example.com/2010/03/1234.html" ))) ); assert_eq!( header.author(), Some("John Doe ".to_string()) ); assert_eq!(header.reviewed_by(), Vec::<&str>::new()); assert_eq!( header.last_update(), Some(chrono::NaiveDate::from_ymd_opt(2010, 3, 29).unwrap()) ); assert_eq!( header.applied_upstream(), Some(super::AppliedUpstream::Other(Cow::Borrowed( "1.2, http://bzr.example.com/frobnicator/trunk/revision/123" ))) ); assert_eq!(header.bugs().collect::>(), vec![]); assert_eq!( header.description(), Some("Fix widget frobnication speeds".to_string()) ); } #[test] fn test_vendor_bugs() { let text = r#"Description: Fix widget frobnication speeds Bug: http://bugs.example.com/123 Bug-Debian: http://bugs.debian.org/123 Bug-Ubuntu: http://bugs.launchpad.net/123 "#; let header = PatchHeader::from_str(text).unwrap(); assert_eq!( header.vendor_bugs("Debian").collect::>(), vec!["http://bugs.debian.org/123".to_string()] ); assert_eq!( header.vendor_bugs("Ubuntu").collect::>(), vec!["http://bugs.launchpad.net/123".to_string()] ); } #[test] fn test_set_last_update() { let text = r#"Description: Fix widget frobnication speeds "#; let mut header = PatchHeader::from_str(text).unwrap(); let date = chrono::NaiveDate::from_ymd_opt(2023, 5, 15).unwrap(); header.set_last_update(date); assert_eq!(header.last_update(), Some(date)); } } dep3-0.2.1/src/lossy.rs000064400000000000000000000227171046102023000127760ustar 00000000000000//! A library for parsing and generating Debian patch headers. //! //! # Examples //! //! ```rust //! use dep3::lossy::PatchHeader; //! use std::str::FromStr; //! let text = r#"From: John Doe //! Date: Mon, 1 Jan 2000 00:00:00 +0000 //! Subject: [PATCH] fix a bug //! Bug-Debian: https://bugs.debian.org/123456 //! Bug: https://bugzilla.example.com/bug.cgi?id=123456 //! Forwarded: not-needed //! "#; //! //! let patch_header = PatchHeader::from_str(text).unwrap(); //! assert_eq!(patch_header.description, Some("[PATCH] fix a bug".to_string())); //! assert_eq!(patch_header.bug_debian, Some("https://bugs.debian.org/123456".parse().unwrap())); //! ``` use crate::fields::*; use deb822_fast::{FromDeb822, FromDeb822Paragraph, Paragraph, ToDeb822, ToDeb822Paragraph}; fn deserialize_date(s: &str) -> Result { chrono::NaiveDate::parse_from_str(s, "%Y-%m-%d").map_err(|e| e.to_string()) } fn serialize_date(date: &chrono::NaiveDate) -> String { date.format("%Y-%m-%d").to_string() } fn deserialize_origin(s: &str) -> Result<(Option, Origin), String> { Ok(crate::fields::parse_origin(s)) } fn serialize_origin((category, origin): &(Option, Origin)) -> String { crate::fields::format_origin(category, origin) } /// A patch header. #[derive(Debug, Clone, PartialEq, FromDeb822, ToDeb822)] pub struct PatchHeader { #[deb822(field = "Origin", serialize_with = serialize_origin, deserialize_with = deserialize_origin)] /// The origin of the patch. pub origin: Option<(Option, Origin)>, #[deb822(field = "Forwarded")] /// Whether the patch has been forwarded upstream. pub forwarded: Option, #[deb822(field = "Author")] /// The author of the patch. pub author: Option, #[deb822(field = "Reviewed-by")] /// The person who reviewed the patch. pub reviewed_by: Option, #[deb822(field = "Bug-Debian")] /// The URL of the Debian bug report. pub bug_debian: Option, #[deb822(field = "Last-Update", deserialize_with = deserialize_date, serialize_with = serialize_date)] /// The date of the last update. pub last_update: Option, #[deb822(field = "Applied-Upstream")] /// Whether the patch has been applied upstream. pub applied_upstream: Option, #[deb822(field = "Bug")] /// The URL of the upstream bug report. pub bug: Option, #[deb822(field = "Description")] /// The description of the patch. pub description: Option, } impl PatchHeader { /// Create a new patch header. pub fn vendor_bugs(&self, vendor: &str) -> Option<&str> { match vendor { "Debian" => self.bug_debian.as_ref().map(|u| u.as_str()), _ => None, } } } impl std::fmt::Display for PatchHeader { fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { let paragraph: deb822_fast::Paragraph = self.to_paragraph(); paragraph.fmt(f) } } impl std::str::FromStr for PatchHeader { type Err = String; fn from_str(s: &str) -> Result { let paragraph = Paragraph::from_str(s).map_err(|e| e.to_string())?; let mut header = PatchHeader::from_paragraph(¶graph)?; if header.author.is_none() { header.author = paragraph.get("From").map(ToString::to_string); } if header.description.is_none() { header.description = paragraph.get("Subject").map(ToString::to_string); } Ok(header) } } #[cfg(test)] mod tests { use super::PatchHeader; use std::borrow::Cow; #[test] fn test_upstream() { let text = r#"From: Ulrich Drepper Subject: Fix regex problems with some multi-bytes characters * posix/bug-regex17.c: Add testcases. * posix/regcomp.c (re_compile_fastmap_iter): Rewrite COMPLEX_BRACKET handling. Origin: upstream, http://sourceware.org/git/?p=glibc.git;a=commitdiff;h=bdb56bac Bug: http://sourceware.org/bugzilla/show_bug.cgi?id=9697 Bug-Debian: http://bugs.debian.org/510219 "#; let header: PatchHeader = text.parse().unwrap(); assert_eq!( header.origin, Some(( Some(super::OriginCategory::Upstream), super::Origin::Other(Cow::Borrowed( "http://sourceware.org/git/?p=glibc.git;a=commitdiff;h=bdb56bac" )) )) ); assert_eq!(header.forwarded, None); assert_eq!( header.author, Some("Ulrich Drepper ".to_string()) ); assert_eq!(header.reviewed_by, None); assert_eq!(header.last_update, None); assert_eq!(header.applied_upstream, None); assert_eq!( header.bug, "http://sourceware.org/bugzilla/show_bug.cgi?id=9697" .parse() .ok() ); assert_eq!( header.bug_debian, "http://bugs.debian.org/510219".parse().ok() ); assert_eq!( header.description, Some("Fix regex problems with some multi-bytes characters\n\n* posix/bug-regex17.c: Add testcases.\n* posix/regcomp.c (re_compile_fastmap_iter): Rewrite COMPLEX_BRACKET\nhandling.\n".to_string()) ); } #[test] fn test_forwarded() { let text = r#"Description: Use FHS compliant paths by default Upstream is not interested in switching to those paths. . But we will continue using them in Debian nevertheless to comply with our policy. Forwarded: http://lists.example.com/oct-2006/1234.html Author: John Doe Last-Update: 2006-12-21 "#; let header: PatchHeader = text.parse().unwrap(); assert_eq!(header.origin, None); assert_eq!( header.forwarded, Some(super::Forwarded::Yes(Cow::Borrowed( "http://lists.example.com/oct-2006/1234.html" ))) ); assert_eq!( header.author, Some("John Doe ".to_string()) ); assert_eq!(header.reviewed_by, None); assert_eq!( header.last_update, Some(chrono::NaiveDate::from_ymd_opt(2006, 12, 21).unwrap()) ); assert_eq!(header.applied_upstream, None); assert_eq!( header.description, Some("Use FHS compliant paths by default\nUpstream is not interested in switching to those paths.\n.\nBut we will continue using them in Debian nevertheless to comply with\nour policy.".to_string()) ); } #[test] fn test_not_forwarded() { let text = r#"Description: Workaround for broken symbol resolving on mips/mipsel The correct fix will be done in etch and it will require toolchain fixes. Forwarded: not-needed Origin: vendor, http://bugs.debian.org/cgi-bin/bugreport.cgi?msg=80;bug=265678 Bug-Debian: http://bugs.debian.org/265678 Author: Thiemo Seufer "#; let header: PatchHeader = text.parse().unwrap(); assert_eq!( header.origin, Some(( Some(super::OriginCategory::Vendor), super::Origin::Other(Cow::Borrowed( "http://bugs.debian.org/cgi-bin/bugreport.cgi?msg=80;bug=265678" )) )) ); assert_eq!(header.forwarded, Some(super::Forwarded::NotNeeded)); assert_eq!( header.author, Some("Thiemo Seufer ".to_string()) ); assert_eq!(header.reviewed_by, None); assert_eq!(header.last_update, None); assert_eq!(header.applied_upstream, None); assert_eq!( header.bug_debian, "http://bugs.debian.org/265678".parse().ok() ); assert_eq!( header.description, Some( "Workaround for broken symbol resolving on mips/mipsel The correct fix will be done in etch and it will require toolchain fixes." .to_string() ) ); } #[test] fn test_applied_upstream() { let text = r#"Description: Fix widget frobnication speeds Frobnicating widgets too quickly tended to cause explosions. Forwarded: http://lists.example.com/2010/03/1234.html Author: John Doe Applied-Upstream: 1.2, http://bzr.example.com/frobnicator/trunk/revision/123 Last-Update: 2010-03-29 "#; let header: PatchHeader = text.parse().unwrap(); assert_eq!(header.origin, None); assert_eq!( header.forwarded, Some(super::Forwarded::Yes(Cow::Borrowed( "http://lists.example.com/2010/03/1234.html" ))) ); assert_eq!( header.author, Some("John Doe ".to_string()) ); assert_eq!(header.reviewed_by, None); assert_eq!( header.last_update, Some(chrono::NaiveDate::from_ymd_opt(2010, 3, 29).unwrap()) ); assert_eq!( header.applied_upstream, Some(super::AppliedUpstream::Other(Cow::Borrowed( "1.2, http://bzr.example.com/frobnicator/trunk/revision/123" ))) ); assert_eq!( header.description, Some("Fix widget frobnication speeds\nFrobnicating widgets too quickly tended to cause explosions.".to_string()) ); } }