debian-analyzer-0.158.27/.cargo_vcs_info.json0000644000000001460000000000100143460ustar { "git": { "sha1": "d86a0fbd65e54f27d9312043d371d06686688cbd" }, "path_in_vcs": "analyzer" }debian-analyzer-0.158.27/Cargo.lock0000644000002566220000000000100123350ustar # This file is automatically @generated by Cargo. # It is not intended for manual editing. version = 4 [[package]] name = "addr2line" version = "0.24.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dfbe277e56a376000877090da837660b4427aad530e3028d44e0bffe4f89a1c1" dependencies = [ "gimli", ] [[package]] name = "adler2" version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "512761e0bb2578dd7380c6baaa0f4ce03e84f95e960231d1dec8bf4d7d6e2627" [[package]] name = "aho-corasick" version = "1.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916" dependencies = [ "memchr", ] [[package]] name = "allocator-api2" version = "0.2.21" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "683d7910e743518b0e34f1186f92494becacb047c7b6bf616c96772180fef923" [[package]] name = "android-tzdata" version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e999941b234f3131b00bc13c22d06e8c5ff726d1b6318ac7eb276997bbb4fef0" [[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 = "anstream" version = "0.6.18" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8acc5369981196006228e28809f761875c0327210a891e941f4c683b3a99529b" dependencies = [ "anstyle", "anstyle-parse", "anstyle-query", "anstyle-wincon", "colorchoice", "is_terminal_polyfill", "utf8parse", ] [[package]] name = "anstyle" version = "1.0.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "55cc3b69f167a1ef2e161439aa98aed94e6028e5f9a59be9a6ffb47aef1651f9" [[package]] name = "anstyle-parse" version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3b2d16507662817a6a20a9ea92df6652ee4f94f914589377d69f3b21bc5798a9" dependencies = [ "utf8parse", ] [[package]] name = "anstyle-query" version = "1.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "79947af37f4177cfead1110013d678905c37501914fba0efea834c3fe9a8d60c" dependencies = [ "windows-sys 0.59.0", ] [[package]] name = "anstyle-wincon" version = "3.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ca3534e77181a9cc07539ad51f2141fe32f6c3ffd4df76db8ad92346b003ae4e" dependencies = [ "anstyle", "once_cell", "windows-sys 0.59.0", ] [[package]] name = "atoi" version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f28d99ec8bfea296261ca1af174f24225171fea9664ba9003cbebee704810528" dependencies = [ "num-traits", ] [[package]] name = "atomic-waker" version = "1.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1505bd5d3d116872e7271a6d4e16d81d0c8570876c8de68093a09ac269d8aac0" [[package]] name = "autocfg" version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26" [[package]] name = "backtrace" version = "0.3.74" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8d82cb332cdfaed17ae235a638438ac4d4839913cc2af585c3c6746e8f8bee1a" dependencies = [ "addr2line", "cfg-if", "libc", "miniz_oxide", "object", "rustc-demangle", "windows-targets 0.52.6", ] [[package]] name = "base64" version = "0.22.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" [[package]] name = "base64ct" version = "1.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "89e25b6adfb930f02d1981565a6e5d9c547ac15a96606256d3b59040e5cd4ca3" [[package]] name = "bitflags" version = "1.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] name = "bitflags" version = "2.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5c8214115b7bf84099f1309324e63141d4c5d7cc26862f97a0a857dbefe165bd" dependencies = [ "serde", ] [[package]] name = "block-buffer" version = "0.10.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71" dependencies = [ "generic-array", ] [[package]] name = "breezyshim" version = "0.1.227" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ffe63ba40f1cf5aed5af3577f45cc5692e69f9bbf7b12950a87dd2469b9c3183" dependencies = [ "chrono", "ctor", "debian-changelog", "debian-control", "debversion", "difflib", "dirty-tracker", "lazy-regex", "lazy_static", "log", "patchkit", "percent-encoding", "pyo3", "pyo3-filelike", "serde", "tempfile", "url", ] [[package]] name = "bumpalo" version = "3.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1628fb46dfa0b37568d12e5edd512553eccf6a22a78e8bde00bb4aed84d5bdbf" [[package]] name = "byteorder" version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" [[package]] name = "bytes" version = "1.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d71b6127be86fdcfddb610f7182ac57211d4b18a3e9c82eb2d17662f2227ad6a" [[package]] name = "cc" version = "1.2.19" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8e3a13707ac958681c13b39b458c073d0d9bc8a22cb1b2f4c8e55eb72c13f362" dependencies = [ "shlex", ] [[package]] name = "cfg-if" version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] name = "chrono" version = "0.4.40" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1a7964611d71df112cb1730f2ee67324fcf4d0fc6606acbbe9bfe06df124637c" dependencies = [ "android-tzdata", "iana-time-zone", "js-sys", "num-traits", "serde", "wasm-bindgen", "windows-link", ] [[package]] name = "clap" version = "4.5.37" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "eccb054f56cbd38340b380d4a8e69ef1f02f1af43db2f0cc817a4774d80ae071" dependencies = [ "clap_builder", "clap_derive", ] [[package]] name = "clap_builder" version = "4.5.37" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "efd9466fac8543255d3b1fcad4762c5e116ffe808c8a3043d4263cd4fd4862a2" dependencies = [ "anstream", "anstyle", "clap_lex", "strsim", ] [[package]] name = "clap_derive" version = "4.5.32" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "09176aae279615badda0765c0c0b3f6ed53f4709118af73cf4655d85d1530cd7" dependencies = [ "heck", "proc-macro2", "quote", "syn 2.0.100", ] [[package]] name = "clap_lex" version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f46ad14479a25103f283c0f10005961cf086d8dc42205bb44c46ac563475dca6" [[package]] name = "colorchoice" version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5b63caa9aa9397e2d9480a9b13673856c78d8ac123288526c37d7839f2a86990" [[package]] name = "concurrent-queue" version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4ca0197aee26d1ae37445ee532fefce43251d24cc7c166799f4d46817f1d3973" dependencies = [ "crossbeam-utils", ] [[package]] name = "configparser" version = "3.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e57e3272f0190c3f1584272d613719ba5fc7df7f4942fe542e63d949cf3a649b" [[package]] name = "const-oid" version = "0.9.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c2459377285ad874054d797f3ccebf984978aa39129f6eafde5cdc8315b612f8" [[package]] name = "core-foundation" version = "0.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "91e195e091a93c46f7102ec7818a2aa394e1e1771c3ab4825963fa03e45afb8f" dependencies = [ "core-foundation-sys", "libc", ] [[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 = "cpufeatures" version = "0.2.17" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "59ed5838eebb26a2bb2e58f6d5b5316989ae9d08bab10e0e6d103e656d1b0280" dependencies = [ "libc", ] [[package]] name = "crc" version = "3.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "69e6e4d7b33a94f0991c26729976b10ebde1d34c3ee82408fb536164fa10d636" dependencies = [ "crc-catalog", ] [[package]] name = "crc-catalog" version = "2.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "19d374276b40fb8bbdee95aef7c7fa6b5316ec764510eb64b8dd0e2ed0d7e7f5" [[package]] name = "crossbeam-channel" version = "0.5.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "82b8f8f868b36967f9606790d1903570de9ceaf870a7bf9fbbd3016d636a2cb2" dependencies = [ "crossbeam-utils", ] [[package]] name = "crossbeam-queue" version = "0.3.12" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0f58bbc28f91df819d0aa2a2c00cd19754769c2fad90579b3592b1c9ba7a3115" dependencies = [ "crossbeam-utils", ] [[package]] name = "crossbeam-utils" version = "0.8.21" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28" [[package]] name = "crypto-common" version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" dependencies = [ "generic-array", "typenum", ] [[package]] name = "csv" version = "1.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "acdc4883a9c96732e4733212c01447ebd805833b7275a73ca3ee080fd77afdaf" dependencies = [ "csv-core", "itoa", "ryu", "serde", ] [[package]] name = "csv-core" version = "0.1.12" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7d02f3b0da4c6504f86e9cd789d8dbafab48c2321be74e9987593de5a894d93d" dependencies = [ "memchr", ] [[package]] name = "ctor" version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "07e9666f4a9a948d4f1dff0c08a4512b0f7c86414b23960104c243c10d79f4c3" dependencies = [ "ctor-proc-macro", "dtor", ] [[package]] name = "ctor-proc-macro" version = "0.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4f211af61d8efdd104f96e57adf5e426ba1bc3ed7a4ead616e15e5881fd79c4d" [[package]] name = "deb822-derive" version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7b6e5cafe61e77421a090e2a33b8a2e4e2ff1b106fd906ebade111307064d981" dependencies = [ "proc-macro2", "quote", "syn 2.0.100", ] [[package]] name = "deb822-lossless" version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "812bb5c8052a89edc6d45d1bc3b3400e8186dd166e9b0a9520bfa5a2bd8477ee" dependencies = [ "deb822-derive", "pyo3", "regex", "rowan 0.16.1", "serde", ] [[package]] name = "debian-analyzer" version = "0.158.27" dependencies = [ "breezyshim", "chrono", "clap", "configparser", "deb822-lossless", "debian-changelog", "debian-control", "debian-copyright", "debversion", "dep3", "difflib", "distro-info", "env_logger", "filetime", "hex", "lazy-regex", "lazy_static", "log", "makefile-lossless", "maplit", "merge3", "patchkit", "pyo3", "quote", "reqwest", "semver", "serde", "serde_json", "serial_test", "sha1", "sqlx", "svp-client", "tempfile", "toml_edit", "url", ] [[package]] name = "debian-changelog" version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "98258e2066472d8d04bfe8a3fab2e7be77fe87b913dab2308a59f13061145814" dependencies = [ "chrono", "debversion", "lazy-regex", "log", "rowan 0.15.16", "textwrap", "whoami", ] [[package]] name = "debian-control" version = "0.1.41" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f9e04c1b1377047a3ee5ef6914f48187fd363f6e9287c3e6d72539f0a8cc2573" dependencies = [ "chrono", "deb822-lossless", "debversion", "pyo3", "regex", "rowan 0.16.1", "url", ] [[package]] name = "debian-copyright" version = "0.1.27" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e893a383c33c4e2689fd3c3121d6e82193211f65e7c483463c816f6b7c29857e" dependencies = [ "deb822-lossless", "debversion", "regex", ] [[package]] name = "debversion" version = "0.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b892997e53d52f9ac5c30bdac09cbea6bb1eeb3f93a204b8548774081a44b496" dependencies = [ "chrono", "lazy-regex", "pyo3", "serde", ] [[package]] name = "dep3" version = "0.1.28" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "22009dcff95c439fb3317f9726556e9e3e5ece2ec7c249b667a66f8f35e05018" dependencies = [ "chrono", "deb822-lossless", "url", ] [[package]] name = "der" version = "0.7.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e7c1832837b905bbfb5101e07cc24c8deddf52f93225eee6ead5f4d63d53ddcb" dependencies = [ "const-oid", "pem-rfc7468", "zeroize", ] [[package]] name = "difflib" version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6184e33543162437515c2e2b48714794e37845ec9851711914eec9d308f6ebe8" [[package]] name = "digest" version = "0.10.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" dependencies = [ "block-buffer", "const-oid", "crypto-common", "subtle", ] [[package]] name = "dirty-tracker" version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "57f673af5cabab0d10b822fae4b348c2f5fdc56d90474e26f5dcde0f94fce488" dependencies = [ "notify", "tempfile", ] [[package]] name = "displaydoc" version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0" dependencies = [ "proc-macro2", "quote", "syn 2.0.100", ] [[package]] name = "distro-info" version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ef12237f2ced990e453ec0b69230752e73be0a357817448c50a62f8bbbe0ca71" dependencies = [ "chrono", "csv", "failure", ] [[package]] name = "dotenvy" version = "0.15.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1aaf95b3e5c8f23aa320147307562d361db0ae0d51242340f558153b4eb2439b" [[package]] name = "dtor" version = "0.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "222ef136a1c687d4aa0395c175f2c4586e379924c352fd02f7870cf7de783c23" dependencies = [ "dtor-proc-macro", ] [[package]] name = "dtor-proc-macro" version = "0.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7454e41ff9012c00d53cf7f475c5e3afa3b91b7c90568495495e8d9bf47a1055" [[package]] name = "either" version = "1.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "48c757948c5ede0e46177b7add2e67155f70e33c07fea8284df6576da70b3719" dependencies = [ "serde", ] [[package]] name = "encoding_rs" version = "0.8.35" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "75030f3c4f45dafd7586dd6780965a8c7e8e285a5ecb86713e63a79c5b2766f3" dependencies = [ "cfg-if", ] [[package]] name = "env_filter" version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "186e05a59d4c50738528153b83b0b0194d3a29507dfec16eccd4b342903397d0" dependencies = [ "log", "regex", ] [[package]] name = "env_logger" version = "0.11.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "13c863f0904021b108aa8b2f55046443e6b1ebde8fd4a15c399893aae4fa069f" dependencies = [ "anstream", "anstyle", "env_filter", "jiff", "log", ] [[package]] name = "equivalent" version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f" [[package]] name = "errno" version = "0.3.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "976dd42dc7e85965fe702eb8164f21f450704bdde31faefd6471dba214cb594e" dependencies = [ "libc", "windows-sys 0.59.0", ] [[package]] name = "etcetera" version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "136d1b5283a1ab77bd9257427ffd09d8667ced0570b6f938942bc7568ed5b943" dependencies = [ "cfg-if", "home", "windows-sys 0.48.0", ] [[package]] name = "event-listener" version = "5.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3492acde4c3fc54c845eaab3eed8bd00c7a7d881f78bfc801e43a93dec1331ae" dependencies = [ "concurrent-queue", "parking", "pin-project-lite", ] [[package]] name = "failure" version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d32e9bd16cc02eae7db7ef620b392808b89f6a5e16bb3497d159c6b92a0f4f86" dependencies = [ "backtrace", "failure_derive", ] [[package]] name = "failure_derive" version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "aa4da3c766cd7a0db8242e326e9e4e081edd567072893ed320008189715366a4" dependencies = [ "proc-macro2", "quote", "syn 1.0.109", "synstructure 0.12.6", ] [[package]] name = "fastrand" version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "37909eebbb50d72f9059c3b6d82c0463f2ff062c9e95845c43a6c9c0355411be" [[package]] name = "filetime" version = "0.2.25" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "35c0522e981e68cbfa8c3f978441a5f34b30b96e146b33cd3359176b50fe8586" dependencies = [ "cfg-if", "libc", "libredox", "windows-sys 0.59.0", ] [[package]] name = "flume" version = "0.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "da0e4dd2a88388a1f4ccc7c9ce104604dab68d9f408dc34cd45823d5a9069095" dependencies = [ "futures-core", "futures-sink", "spin", ] [[package]] name = "fnv" version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" [[package]] name = "foldhash" version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d9c4f5dac5e15c24eb999c26181a6ca40b39fe946cbe4c263c7209467bc83af2" [[package]] name = "foreign-types" version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1" dependencies = [ "foreign-types-shared", ] [[package]] name = "foreign-types-shared" version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" [[package]] name = "form_urlencoded" version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e13624c2627564efccf4934284bdd98cbaa14e79b0b5a141218e507b3a823456" dependencies = [ "percent-encoding", ] [[package]] name = "fsevent-sys" version = "4.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "76ee7a02da4d231650c7cea31349b889be2f45ddb3ef3032d2ec8185f6313fd2" dependencies = [ "libc", ] [[package]] name = "futures" version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "65bc07b1a8bc7c85c5f2e110c476c7389b4554ba72af57d8445ea63a576b0876" dependencies = [ "futures-channel", "futures-core", "futures-executor", "futures-io", "futures-sink", "futures-task", "futures-util", ] [[package]] name = "futures-channel" version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2dff15bf788c671c1934e366d07e30c1814a8ef514e1af724a602e8a2fbe1b10" dependencies = [ "futures-core", "futures-sink", ] [[package]] name = "futures-core" version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "05f29059c0c2090612e8d742178b0580d2dc940c837851ad723096f87af6663e" [[package]] name = "futures-executor" version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1e28d1d997f585e54aebc3f97d39e72338912123a67330d723fdbb564d646c9f" dependencies = [ "futures-core", "futures-task", "futures-util", ] [[package]] name = "futures-intrusive" version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1d930c203dd0b6ff06e0201a4a2fe9149b43c684fd4420555b26d21b1a02956f" dependencies = [ "futures-core", "lock_api", "parking_lot", ] [[package]] name = "futures-io" version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9e5c1b78ca4aae1ac06c48a526a655760685149f0d465d21f37abfe57ce075c6" [[package]] name = "futures-sink" version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e575fab7d1e0dcb8d0c7bcf9a63ee213816ab51902e6d244a95819acacf1d4f7" [[package]] name = "futures-task" version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f90f7dce0722e95104fcb095585910c0977252f286e354b5e3bd38902cd99988" [[package]] name = "futures-util" version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9fa08315bb612088cc391249efdc3bc77536f16c91f6cf495e6fbe85b20a4a81" dependencies = [ "futures-channel", "futures-core", "futures-io", "futures-sink", "futures-task", "memchr", "pin-project-lite", "pin-utils", "slab", ] [[package]] name = "generic-array" version = "0.14.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" dependencies = [ "typenum", "version_check", ] [[package]] name = "getrandom" version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7" dependencies = [ "cfg-if", "libc", "wasi 0.11.0+wasi-snapshot-preview1", ] [[package]] name = "getrandom" version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "73fea8450eea4bac3940448fb7ae50d91f034f941199fcd9d909a5a07aa455f0" dependencies = [ "cfg-if", "libc", "r-efi", "wasi 0.14.2+wasi-0.2.4", ] [[package]] name = "gimli" version = "0.31.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "07e28edb80900c19c28f1072f2e8aeca7fa06b23cd4169cefe1af5aa3260783f" [[package]] name = "h2" version = "0.4.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "75249d144030531f8dee69fe9cea04d3edf809a017ae445e2abdff6629e86633" dependencies = [ "atomic-waker", "bytes", "fnv", "futures-core", "futures-sink", "http", "indexmap", "slab", "tokio", "tokio-util", "tracing", ] [[package]] name = "hashbrown" version = "0.14.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" [[package]] name = "hashbrown" version = "0.15.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bf151400ff0baff5465007dd2f3e717f3fe502074ca563069ce3a6629d07b289" dependencies = [ "allocator-api2", "equivalent", "foldhash", ] [[package]] name = "hashlink" version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7382cf6263419f2d8df38c55d7da83da5c18aef87fc7a7fc1fb1e344edfe14c1" dependencies = [ "hashbrown 0.15.2", ] [[package]] name = "heck" version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" [[package]] name = "hex" version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" [[package]] name = "hkdf" version = "0.12.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7b5f8eb2ad728638ea2c7d47a21db23b7b58a72ed6a38256b8a1849f15fbbdf7" dependencies = [ "hmac", ] [[package]] name = "hmac" version = "0.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6c49c37c09c17a53d937dfbb742eb3a961d65a994e6bcdcf37e7399d0cc8ab5e" dependencies = [ "digest", ] [[package]] name = "home" version = "0.5.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "589533453244b0995c858700322199b2becb13b627df2851f64a2775d024abcf" dependencies = [ "windows-sys 0.59.0", ] [[package]] name = "http" version = "1.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f4a85d31aea989eead29a3aaf9e1115a180df8282431156e533de47660892565" dependencies = [ "bytes", "fnv", "itoa", ] [[package]] name = "http-body" version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1efedce1fb8e6913f23e0c92de8e62cd5b772a67e7b3946df930a62566c93184" dependencies = [ "bytes", "http", ] [[package]] name = "http-body-util" version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b021d93e26becf5dc7e1b75b1bed1fd93124b374ceb73f43d4d4eafec896a64a" dependencies = [ "bytes", "futures-core", "http", "http-body", "pin-project-lite", ] [[package]] name = "httparse" version = "1.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6dbf3de79e51f3d586ab4cb9d5c3e2c14aa28ed23d180cf89b4df0454a69cc87" [[package]] name = "hyper" version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cc2b571658e38e0c01b1fdca3bbbe93c00d3d71693ff2770043f8c29bc7d6f80" dependencies = [ "bytes", "futures-channel", "futures-util", "h2", "http", "http-body", "httparse", "itoa", "pin-project-lite", "smallvec", "tokio", "want", ] [[package]] name = "hyper-rustls" version = "0.27.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2d191583f3da1305256f22463b9bb0471acad48a4e534a5218b9963e9c1f59b2" dependencies = [ "futures-util", "http", "hyper", "hyper-util", "rustls", "rustls-pki-types", "tokio", "tokio-rustls", "tower-service", ] [[package]] name = "hyper-tls" version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "70206fc6890eaca9fde8a0bf71caa2ddfc9fe045ac9e5c70df101a7dbde866e0" dependencies = [ "bytes", "http-body-util", "hyper", "hyper-util", "native-tls", "tokio", "tokio-native-tls", "tower-service", ] [[package]] name = "hyper-util" version = "0.1.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "497bbc33a26fdd4af9ed9c70d63f61cf56a938375fbb32df34db9b1cd6d643f2" dependencies = [ "bytes", "futures-channel", "futures-util", "http", "http-body", "hyper", "libc", "pin-project-lite", "socket2", "tokio", "tower-service", "tracing", ] [[package]] name = "iana-time-zone" version = "0.1.63" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b0c919e5debc312ad217002b8048a17b7d83f80703865bbfcfebb0458b0b27d8" 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 = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "db2fa452206ebee18c4b5c2274dbf1de17008e874b4dc4f0aea9d01ca79e4526" dependencies = [ "displaydoc", "yoke", "zerofrom", "zerovec", ] [[package]] name = "icu_locid" version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "13acbb8371917fc971be86fc8057c41a64b521c184808a698c02acc242dbf637" dependencies = [ "displaydoc", "litemap", "tinystr", "writeable", "zerovec", ] [[package]] name = "icu_locid_transform" version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "01d11ac35de8e40fdeda00d9e1e9d92525f3f9d887cdd7aa81d727596788b54e" dependencies = [ "displaydoc", "icu_locid", "icu_locid_transform_data", "icu_provider", "tinystr", "zerovec", ] [[package]] name = "icu_locid_transform_data" version = "1.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7515e6d781098bf9f7205ab3fc7e9709d34554ae0b21ddbcb5febfa4bc7df11d" [[package]] name = "icu_normalizer" version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "19ce3e0da2ec68599d193c93d088142efd7f9c5d6fc9b803774855747dc6a84f" dependencies = [ "displaydoc", "icu_collections", "icu_normalizer_data", "icu_properties", "icu_provider", "smallvec", "utf16_iter", "utf8_iter", "write16", "zerovec", ] [[package]] name = "icu_normalizer_data" version = "1.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c5e8338228bdc8ab83303f16b797e177953730f601a96c25d10cb3ab0daa0cb7" [[package]] name = "icu_properties" version = "1.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "93d6020766cfc6302c15dbbc9c8778c37e62c14427cb7f6e601d849e092aeef5" dependencies = [ "displaydoc", "icu_collections", "icu_locid_transform", "icu_properties_data", "icu_provider", "tinystr", "zerovec", ] [[package]] name = "icu_properties_data" version = "1.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "85fb8799753b75aee8d2a21d7c14d9f38921b54b3dbda10f5a3c7a7b82dba5e2" [[package]] name = "icu_provider" version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6ed421c8a8ef78d3e2dbc98a973be2f3770cb42b606e3ab18d6237c4dfde68d9" dependencies = [ "displaydoc", "icu_locid", "icu_provider_macros", "stable_deref_trait", "tinystr", "writeable", "yoke", "zerofrom", "zerovec", ] [[package]] name = "icu_provider_macros" version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1ec89e9337638ecdc08744df490b221a7399bf8d164eb52a665454e60e075ad6" dependencies = [ "proc-macro2", "quote", "syn 2.0.100", ] [[package]] name = "idna" version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "686f825264d630750a544639377bae737628043f20d38bbc029e8f29ea968a7e" dependencies = [ "idna_adapter", "smallvec", "utf8_iter", ] [[package]] name = "idna_adapter" version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "daca1df1c957320b2cf139ac61e7bd64fed304c5040df000a745aa1de3b4ef71" dependencies = [ "icu_normalizer", "icu_properties", ] [[package]] name = "indexmap" version = "2.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cea70ddb795996207ad57735b50c5982d8844f38ba9ee5f1aedcfb708a2aa11e" dependencies = [ "equivalent", "hashbrown 0.15.2", ] [[package]] name = "indoc" version = "2.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f4c7245a08504955605670dbf141fceab975f15ca21570696aebe9d2e71576bd" [[package]] name = "inotify" version = "0.9.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f8069d3ec154eb856955c1c0fbffefbf5f3c40a104ec912d4797314c1801abff" dependencies = [ "bitflags 1.3.2", "inotify-sys", "libc", ] [[package]] name = "inotify-sys" version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e05c02b5e89bff3b946cedeca278abc628fe811e604f027c45a8aa3cf793d0eb" dependencies = [ "libc", ] [[package]] name = "ipnet" version = "2.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "469fb0b9cefa57e3ef31275ee7cacb78f2fdca44e4765491884a2b119d4eb130" [[package]] name = "is_terminal_polyfill" version = "1.70.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7943c866cc5cd64cbc25b2e01621d07fa8eb2a1a23160ee81ce38704e97b8ecf" [[package]] name = "itoa" version = "1.0.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c" [[package]] name = "jiff" version = "0.2.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "59ec30f7142be6fe14e1b021f50b85db8df2d4324ea6e91ec3e5dcde092021d0" dependencies = [ "jiff-static", "log", "portable-atomic", "portable-atomic-util", "serde", ] [[package]] name = "jiff-static" version = "0.2.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "526b834d727fd59d37b076b0c3236d9adde1b1729a4361e20b2026f738cc1dbe" dependencies = [ "proc-macro2", "quote", "syn 2.0.100", ] [[package]] name = "js-sys" version = "0.3.77" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1cfaf33c695fc6e08064efbc1f72ec937429614f25eef83af942d0e227c3a28f" dependencies = [ "once_cell", "wasm-bindgen", ] [[package]] name = "kqueue" version = "1.0.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7447f1ca1b7b563588a205fe93dea8df60fd981423a768bc1c0ded35ed147d0c" dependencies = [ "kqueue-sys", "libc", ] [[package]] name = "kqueue-sys" version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ed9625ffda8729b85e45cf04090035ac368927b8cebc34898e7c120f52e4838b" dependencies = [ "bitflags 1.3.2", "libc", ] [[package]] name = "lazy-regex" version = "3.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "60c7310b93682b36b98fa7ea4de998d3463ccbebd94d935d6b48ba5b6ffa7126" dependencies = [ "lazy-regex-proc_macros", "once_cell", "regex", ] [[package]] name = "lazy-regex-proc_macros" version = "3.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4ba01db5ef81e17eb10a5e0f2109d1b3a3e29bac3070fdbd7d156bf7dbd206a1" dependencies = [ "proc-macro2", "quote", "regex", "syn 2.0.100", ] [[package]] name = "lazy_static" version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" dependencies = [ "spin", ] [[package]] name = "libc" version = "0.2.172" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d750af042f7ef4f724306de029d18836c26c1765a54a6a3f094cbd23a7267ffa" [[package]] name = "libm" version = "0.2.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8355be11b20d696c8f18f6cc018c4e372165b1fa8126cef092399c9951984ffa" [[package]] name = "libredox" version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c0ff37bd590ca25063e35af745c343cb7a0271906fb7b37e4813e8f79f00268d" dependencies = [ "bitflags 2.9.0", "libc", "redox_syscall", ] [[package]] name = "libsqlite3-sys" version = "0.30.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2e99fb7a497b1e3339bc746195567ed8d3e24945ecd636e3619d20b9de9e9149" dependencies = [ "pkg-config", "vcpkg", ] [[package]] name = "linux-raw-sys" version = "0.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cd945864f07fe9f5371a27ad7b52a172b4b499999f1d97574c9fa68373937e12" [[package]] name = "litemap" version = "0.7.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "23fb14cb19457329c82206317a5663005a4d404783dc74f4252769b0d5f42856" [[package]] name = "lock_api" version = "0.4.12" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "07af8b9cdd281b7915f413fa73f29ebd5d55d0d3f0155584dade1ff18cea1b17" dependencies = [ "autocfg", "scopeguard", ] [[package]] name = "log" version = "0.4.27" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "13dc2df351e3202783a1fe0d44375f7295ffb4049267b0f3018346dc122a1d94" [[package]] name = "makefile-lossless" version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d336a1f57cdee530a7b9afe7fe297653f8f44d3eaa0e45b05dec8708dfda00ad" dependencies = [ "log", "rowan 0.16.1", ] [[package]] name = "maplit" version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3e2e65a1a2e43cfcb47a895c4c8b10d1f4a61097f9f254f183aee60cad9c651d" [[package]] name = "md-5" version = "0.10.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d89e7ee0cfbedfc4da3340218492196241d89eefb6dab27de5df917a6d2e78cf" dependencies = [ "cfg-if", "digest", ] [[package]] name = "memchr" version = "2.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" [[package]] name = "memoffset" version = "0.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "488016bfae457b036d996092f6cb448677611ce4449e970ceaf42695203f218a" dependencies = [ "autocfg", ] [[package]] name = "merge3" version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b4b277bc3c7e2bc163abc6c0069f53715b52dc34442c0e807cc8758c7113524f" dependencies = [ "clap", "difflib", ] [[package]] name = "mime" version = "0.3.17" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a" [[package]] name = "miniz_oxide" version = "0.8.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3be647b768db090acb35d5ec5db2b0e1f1de11133ca123b9eacf5137868f892a" dependencies = [ "adler2", ] [[package]] name = "mio" version = "0.8.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a4a650543ca06a924e8b371db273b2756685faae30f8487da1b56505a8f78b0c" dependencies = [ "libc", "log", "wasi 0.11.0+wasi-snapshot-preview1", "windows-sys 0.48.0", ] [[package]] name = "mio" version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2886843bf800fba2e3377cff24abf6379b4c4d5c6681eaf9ea5b0d15090450bd" dependencies = [ "libc", "wasi 0.11.0+wasi-snapshot-preview1", "windows-sys 0.52.0", ] [[package]] name = "native-tls" version = "0.2.14" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "87de3442987e9dbec73158d5c715e7ad9072fda936bb03d19d7fa10e00520f0e" dependencies = [ "libc", "log", "openssl", "openssl-probe", "openssl-sys", "schannel", "security-framework", "security-framework-sys", "tempfile", ] [[package]] name = "notify" version = "6.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6205bd8bb1e454ad2e27422015fb5e4f2bcc7e08fa8f27058670d208324a4d2d" dependencies = [ "bitflags 2.9.0", "crossbeam-channel", "filetime", "fsevent-sys", "inotify", "kqueue", "libc", "log", "mio 0.8.11", "walkdir", "windows-sys 0.48.0", ] [[package]] name = "num-bigint-dig" version = "0.8.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dc84195820f291c7697304f3cbdadd1cb7199c0efc917ff5eafd71225c136151" dependencies = [ "byteorder", "lazy_static", "libm", "num-integer", "num-iter", "num-traits", "rand", "smallvec", "zeroize", ] [[package]] name = "num-integer" version = "0.1.46" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7969661fd2958a5cb096e56c8e1ad0444ac2bbcd0061bd28660485a44879858f" dependencies = [ "num-traits", ] [[package]] name = "num-iter" version = "0.1.45" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1429034a0490724d0075ebb2bc9e875d6503c3cf69e235a8941aa757d83ef5bf" dependencies = [ "autocfg", "num-integer", "num-traits", ] [[package]] name = "num-traits" version = "0.2.19" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" dependencies = [ "autocfg", "libm", ] [[package]] name = "object" version = "0.36.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "62948e14d923ea95ea2c7c86c71013138b66525b86bdc08d2dcc262bdb497b87" dependencies = [ "memchr", ] [[package]] name = "once_cell" version = "1.21.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d" [[package]] name = "openssl" version = "0.10.72" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fedfea7d58a1f73118430a55da6a286e7b044961736ce96a16a17068ea25e5da" dependencies = [ "bitflags 2.9.0", "cfg-if", "foreign-types", "libc", "once_cell", "openssl-macros", "openssl-sys", ] [[package]] name = "openssl-macros" version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" dependencies = [ "proc-macro2", "quote", "syn 2.0.100", ] [[package]] name = "openssl-probe" version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d05e27ee213611ffe7d6348b942e8f942b37114c00cc03cec254295a4a17852e" [[package]] name = "openssl-sys" version = "0.9.107" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8288979acd84749c744a9014b4382d42b8f7b2592847b5afb2ed29e5d16ede07" dependencies = [ "cc", "libc", "pkg-config", "vcpkg", ] [[package]] name = "parking" version = "2.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f38d5652c16fde515bb1ecef450ab0f6a219d619a7274976324d5e377f7dceba" [[package]] name = "parking_lot" version = "0.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f1bf18183cf54e8d6059647fc3063646a1801cf30896933ec2311622cc4b9a27" dependencies = [ "lock_api", "parking_lot_core", ] [[package]] name = "parking_lot_core" version = "0.9.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1e401f977ab385c9e4e3ab30627d6f26d00e2c73eef317493c4ec6d468726cf8" dependencies = [ "cfg-if", "libc", "redox_syscall", "smallvec", "windows-targets 0.52.6", ] [[package]] name = "patchkit" version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "31e00ed52656b51f535293e40caf6579b4cf09f25e660fc6e6936ab70e78972f" dependencies = [ "chrono", "lazy-regex", "lazy_static", "once_cell", "regex", ] [[package]] name = "pem-rfc7468" version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "88b39c9bfcfc231068454382784bb460aae594343fb030d46e9f50a645418412" dependencies = [ "base64ct", ] [[package]] name = "percent-encoding" version = "2.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" [[package]] name = "pin-project-lite" version = "0.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3b3cff922bd51709b605d9ead9aa71031d81447142d828eb4a6eba76fe619f9b" [[package]] name = "pin-utils" version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" [[package]] name = "pkcs1" version = "0.7.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c8ffb9f10fa047879315e6625af03c164b16962a5368d724ed16323b68ace47f" dependencies = [ "der", "pkcs8", "spki", ] [[package]] name = "pkcs8" version = "0.10.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f950b2377845cebe5cf8b5165cb3cc1a5e0fa5cfa3e1f7f55707d8fd82e0a7b7" dependencies = [ "der", "spki", ] [[package]] name = "pkg-config" version = "0.3.32" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7edddbd0b52d732b21ad9a5fab5c704c14cd949e5e9a1ec5929a24fded1b904c" [[package]] name = "portable-atomic" version = "1.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "350e9b48cbc6b0e028b0473b114454c6316e57336ee184ceab6e53f72c178b3e" [[package]] name = "portable-atomic-util" version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d8a2f0d8d040d7848a709caf78912debcc3f33ee4b3cac47d73d1e1069e83507" dependencies = [ "portable-atomic", ] [[package]] name = "ppv-lite86" version = "0.2.21" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "85eae3c4ed2f50dcfe72643da4befc30deadb458a9b590d720cde2f2b1e97da9" dependencies = [ "zerocopy", ] [[package]] name = "proc-macro2" version = "1.0.95" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "02b3e5e68a3a1a02aad3ec490a98007cbc13c37cbe84a3cd7b8e406d76e7f778" dependencies = [ "unicode-ident", ] [[package]] name = "pyo3" version = "0.22.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f402062616ab18202ae8319da13fa4279883a2b8a9d9f83f20dbade813ce1884" dependencies = [ "cfg-if", "chrono", "indoc", "libc", "memoffset", "once_cell", "portable-atomic", "pyo3-build-config", "pyo3-ffi", "pyo3-macros", "serde", "unindent", ] [[package]] name = "pyo3-build-config" version = "0.22.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b14b5775b5ff446dd1056212d778012cbe8a0fbffd368029fd9e25b514479c38" dependencies = [ "once_cell", "target-lexicon", ] [[package]] name = "pyo3-ffi" version = "0.22.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9ab5bcf04a2cdcbb50c7d6105de943f543f9ed92af55818fd17b660390fc8636" dependencies = [ "libc", "pyo3-build-config", ] [[package]] name = "pyo3-filelike" version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ddebceed43397d516efc64128026fb9ada97c175a219e63bb1e11edb8b61c3a9" dependencies = [ "pyo3", ] [[package]] name = "pyo3-macros" version = "0.22.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0fd24d897903a9e6d80b968368a34e1525aeb719d568dba8b3d4bfa5dc67d453" dependencies = [ "proc-macro2", "pyo3-macros-backend", "quote", "syn 2.0.100", ] [[package]] name = "pyo3-macros-backend" version = "0.22.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "36c011a03ba1e50152b4b394b479826cad97e7a21eb52df179cd91ac411cbfbe" dependencies = [ "heck", "proc-macro2", "pyo3-build-config", "quote", "syn 2.0.100", ] [[package]] name = "quote" version = "1.0.40" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1885c039570dc00dcb4ff087a89e185fd56bae234ddc7f056a945bf36467248d" dependencies = [ "proc-macro2", ] [[package]] name = "r-efi" version = "5.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "74765f6d916ee2faa39bc8e68e4f3ed8949b48cccdac59983d287a7cb71ce9c5" [[package]] name = "rand" version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" dependencies = [ "libc", "rand_chacha", "rand_core", ] [[package]] name = "rand_chacha" version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" dependencies = [ "ppv-lite86", "rand_core", ] [[package]] name = "rand_core" version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" dependencies = [ "getrandom 0.2.15", ] [[package]] name = "redox_syscall" version = "0.5.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d2f103c6d277498fbceb16e84d317e2a400f160f46904d5f5410848c829511a3" dependencies = [ "bitflags 2.9.0", ] [[package]] name = "regex" version = "1.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b544ef1b4eac5dc2db33ea63606ae9ffcfac26c1416a2806ae0bf5f56b201191" dependencies = [ "aho-corasick", "memchr", "regex-automata", "regex-syntax", ] [[package]] name = "regex-automata" version = "0.4.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "809e8dc61f6de73b46c85f4c96486310fe304c434cfa43669d7b40f711150908" dependencies = [ "aho-corasick", "memchr", "regex-syntax", ] [[package]] name = "regex-syntax" version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c" [[package]] name = "reqwest" version = "0.12.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d19c46a6fdd48bc4dab94b6103fccc55d34c67cc0ad04653aad4ea2a07cd7bbb" dependencies = [ "base64", "bytes", "encoding_rs", "futures-channel", "futures-core", "futures-util", "h2", "http", "http-body", "http-body-util", "hyper", "hyper-rustls", "hyper-tls", "hyper-util", "ipnet", "js-sys", "log", "mime", "native-tls", "once_cell", "percent-encoding", "pin-project-lite", "rustls-pemfile", "serde", "serde_json", "serde_urlencoded", "sync_wrapper", "system-configuration", "tokio", "tokio-native-tls", "tower", "tower-service", "url", "wasm-bindgen", "wasm-bindgen-futures", "web-sys", "windows-registry", ] [[package]] name = "ring" version = "0.17.14" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a4689e6c2294d81e88dc6261c768b63bc4fcdb852be6d1352498b114f61383b7" dependencies = [ "cc", "cfg-if", "getrandom 0.2.15", "libc", "untrusted", "windows-sys 0.52.0", ] [[package]] name = "rowan" version = "0.15.16" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0a542b0253fa46e632d27a1dc5cf7b930de4df8659dc6e720b647fc72147ae3d" dependencies = [ "countme", "hashbrown 0.14.5", "rustc-hash", "text-size", ] [[package]] name = "rowan" version = "0.16.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "417a3a9f582e349834051b8a10c8d71ca88da4211e4093528e36b9845f6b5f21" dependencies = [ "countme", "hashbrown 0.14.5", "rustc-hash", "text-size", ] [[package]] name = "rsa" version = "0.9.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "78928ac1ed176a5ca1d17e578a1825f3d81ca54cf41053a592584b020cfd691b" dependencies = [ "const-oid", "digest", "num-bigint-dig", "num-integer", "num-traits", "pkcs1", "pkcs8", "rand_core", "signature", "spki", "subtle", "zeroize", ] [[package]] name = "rustc-demangle" version = "0.1.24" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f" [[package]] name = "rustc-hash" version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" [[package]] name = "rustix" version = "1.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d97817398dd4bb2e6da002002db259209759911da105da92bec29ccb12cf58bf" dependencies = [ "bitflags 2.9.0", "errno", "libc", "linux-raw-sys", "windows-sys 0.59.0", ] [[package]] name = "rustls" version = "0.23.26" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "df51b5869f3a441595eac5e8ff14d486ff285f7b8c0df8770e49c3b56351f0f0" dependencies = [ "once_cell", "rustls-pki-types", "rustls-webpki", "subtle", "zeroize", ] [[package]] name = "rustls-pemfile" version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dce314e5fee3f39953d46bb63bb8a46d40c2f8fb7cc5a3b6cab2bde9721d6e50" dependencies = [ "rustls-pki-types", ] [[package]] name = "rustls-pki-types" version = "1.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "917ce264624a4b4db1c364dcc35bfca9ded014d0a958cd47ad3e960e988ea51c" [[package]] name = "rustls-webpki" version = "0.103.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fef8b8769aaccf73098557a87cd1816b4f9c7c16811c9c77142aa695c16f2c03" dependencies = [ "ring", "rustls-pki-types", "untrusted", ] [[package]] name = "rustversion" version = "1.0.20" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "eded382c5f5f786b989652c49544c4877d9f015cc22e145a5ea8ea66c2921cd2" [[package]] name = "ryu" version = "1.0.20" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "28d3b2b1366ec20994f1fd18c3c594f05c5dd4bc44d8bb0c1c632c8d6829481f" [[package]] name = "same-file" version = "1.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502" dependencies = [ "winapi-util", ] [[package]] name = "scc" version = "2.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "22b2d775fb28f245817589471dd49c5edf64237f4a19d10ce9a92ff4651a27f4" dependencies = [ "sdd", ] [[package]] name = "schannel" version = "0.1.27" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1f29ebaa345f945cec9fbbc532eb307f0fdad8161f281b6369539c8d84876b3d" dependencies = [ "windows-sys 0.59.0", ] [[package]] name = "scopeguard" version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" [[package]] name = "sdd" version = "3.0.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "584e070911c7017da6cb2eb0788d09f43d789029b5877d3e5ecc8acf86ceee21" [[package]] name = "security-framework" version = "2.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "897b2245f0b511c87893af39b033e5ca9cce68824c4d7e7630b5a1d339658d02" dependencies = [ "bitflags 2.9.0", "core-foundation", "core-foundation-sys", "libc", "security-framework-sys", ] [[package]] name = "security-framework-sys" version = "2.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "49db231d56a190491cb4aeda9527f1ad45345af50b0851622a7adb8c03b01c32" dependencies = [ "core-foundation-sys", "libc", ] [[package]] name = "semver" version = "1.0.26" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "56e6fa9c48d24d85fb3de5ad847117517440f6beceb7798af16b4a87d616b8d0" [[package]] name = "serde" version = "1.0.219" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5f0e2c6ed6606019b4e29e69dbaba95b11854410e5347d525002456dbbb786b6" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" version = "1.0.219" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5b0276cf7f2c73365f7157c8123c21cd9a50fbbd844757af28ca1f5925fc2a00" dependencies = [ "proc-macro2", "quote", "syn 2.0.100", ] [[package]] name = "serde_json" version = "1.0.140" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "20068b6e96dc6c9bd23e01df8827e6c7e1f2fddd43c21810382803c136b99373" dependencies = [ "itoa", "memchr", "ryu", "serde", ] [[package]] name = "serde_urlencoded" version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d3491c14715ca2294c4d6a88f15e84739788c1d030eed8c110436aafdaa2f3fd" dependencies = [ "form_urlencoded", "itoa", "ryu", "serde", ] [[package]] name = "serial_test" version = "3.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1b258109f244e1d6891bf1053a55d63a5cd4f8f4c30cf9a1280989f80e7a1fa9" dependencies = [ "futures", "log", "once_cell", "parking_lot", "scc", "serial_test_derive", ] [[package]] name = "serial_test_derive" version = "3.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5d69265a08751de7844521fd15003ae0a888e035773ba05695c5c759a6f89eef" dependencies = [ "proc-macro2", "quote", "syn 2.0.100", ] [[package]] name = "sha1" version = "0.10.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e3bf829a2d51ab4a5ddf1352d8470c140cadc8301b2ae1789db023f01cedd6ba" dependencies = [ "cfg-if", "cpufeatures", "digest", ] [[package]] name = "sha2" version = "0.10.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "793db75ad2bcafc3ffa7c68b215fee268f537982cd901d132f89c6343f3a3dc8" dependencies = [ "cfg-if", "cpufeatures", "digest", ] [[package]] name = "shlex" version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" [[package]] name = "signature" version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "77549399552de45a898a580c1b41d445bf730df867cc44e6c0233bbc4b8329de" dependencies = [ "digest", "rand_core", ] [[package]] name = "slab" version = "0.4.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8f92a496fb766b417c996b9c5e57daf2f7ad3b0bebe1ccfca4856390e3d3bb67" dependencies = [ "autocfg", ] [[package]] name = "smallvec" version = "1.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8917285742e9f3e1683f0a9c4e6b57960b7314d0b08d30d1ecd426713ee2eee9" dependencies = [ "serde", ] [[package]] name = "smawk" version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b7c388c1b5e93756d0c740965c41e8822f866621d41acbdf6336a6a168f8840c" [[package]] name = "socket2" version = "0.5.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4f5fd57c80058a56cf5c777ab8a126398ece8e442983605d280a44ce79d0edef" dependencies = [ "libc", "windows-sys 0.52.0", ] [[package]] name = "spin" version = "0.9.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67" dependencies = [ "lock_api", ] [[package]] name = "spki" version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d91ed6c858b01f942cd56b37a94b3e0a1798290327d1236e4d9cf4eaca44d29d" dependencies = [ "base64ct", "der", ] [[package]] name = "sqlx" version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f3c3a85280daca669cfd3bcb68a337882a8bc57ec882f72c5d13a430613a738e" dependencies = [ "sqlx-core", "sqlx-macros", "sqlx-mysql", "sqlx-postgres", "sqlx-sqlite", ] [[package]] name = "sqlx-core" version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f743f2a3cea30a58cd479013f75550e879009e3a02f616f18ca699335aa248c3" dependencies = [ "base64", "bytes", "crc", "crossbeam-queue", "either", "event-listener", "futures-core", "futures-intrusive", "futures-io", "futures-util", "hashbrown 0.15.2", "hashlink", "indexmap", "log", "memchr", "once_cell", "percent-encoding", "serde", "serde_json", "sha2", "smallvec", "thiserror", "tracing", "url", ] [[package]] name = "sqlx-macros" version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7f4200e0fde19834956d4252347c12a083bdcb237d7a1a1446bffd8768417dce" dependencies = [ "proc-macro2", "quote", "sqlx-core", "sqlx-macros-core", "syn 2.0.100", ] [[package]] name = "sqlx-macros-core" version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "882ceaa29cade31beca7129b6beeb05737f44f82dbe2a9806ecea5a7093d00b7" dependencies = [ "dotenvy", "either", "heck", "hex", "once_cell", "proc-macro2", "quote", "serde", "serde_json", "sha2", "sqlx-core", "sqlx-mysql", "sqlx-postgres", "sqlx-sqlite", "syn 2.0.100", "tempfile", "url", ] [[package]] name = "sqlx-mysql" version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0afdd3aa7a629683c2d750c2df343025545087081ab5942593a5288855b1b7a7" dependencies = [ "atoi", "base64", "bitflags 2.9.0", "byteorder", "bytes", "crc", "digest", "dotenvy", "either", "futures-channel", "futures-core", "futures-io", "futures-util", "generic-array", "hex", "hkdf", "hmac", "itoa", "log", "md-5", "memchr", "once_cell", "percent-encoding", "rand", "rsa", "serde", "sha1", "sha2", "smallvec", "sqlx-core", "stringprep", "thiserror", "tracing", "whoami", ] [[package]] name = "sqlx-postgres" version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a0bedbe1bbb5e2615ef347a5e9d8cd7680fb63e77d9dafc0f29be15e53f1ebe6" dependencies = [ "atoi", "base64", "bitflags 2.9.0", "byteorder", "crc", "dotenvy", "etcetera", "futures-channel", "futures-core", "futures-util", "hex", "hkdf", "hmac", "home", "itoa", "log", "md-5", "memchr", "once_cell", "rand", "serde", "serde_json", "sha2", "smallvec", "sqlx-core", "stringprep", "thiserror", "tracing", "whoami", ] [[package]] name = "sqlx-sqlite" version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c26083e9a520e8eb87a06b12347679b142dc2ea29e6e409f805644a7a979a5bc" dependencies = [ "atoi", "flume", "futures-channel", "futures-core", "futures-executor", "futures-intrusive", "futures-util", "libsqlite3-sys", "log", "percent-encoding", "serde", "serde_urlencoded", "sqlx-core", "thiserror", "tracing", "url", ] [[package]] name = "stable_deref_trait" version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" [[package]] name = "stringprep" version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7b4df3d392d81bd458a8a621b8bffbd2302a12ffe288a9d931670948749463b1" dependencies = [ "unicode-bidi", "unicode-normalization", "unicode-properties", ] [[package]] name = "strsim" version = "0.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" [[package]] name = "subtle" version = "2.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" [[package]] name = "svp-client" version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8cbf71541e926b5bd10daa99f2f1670a5526b4758aa792ffb45eaaf146add439" dependencies = [ "log", "serde", "serde_json", "url", ] [[package]] name = "syn" version = "1.0.109" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" dependencies = [ "proc-macro2", "quote", "unicode-ident", ] [[package]] name = "syn" version = "2.0.100" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b09a44accad81e1ba1cd74a32461ba89dee89095ba17b32f5d03683b1b1fc2a0" dependencies = [ "proc-macro2", "quote", "unicode-ident", ] [[package]] name = "sync_wrapper" version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0bf256ce5efdfa370213c1dabab5935a12e49f2c58d15e9eac2870d3b4f27263" dependencies = [ "futures-core", ] [[package]] name = "synstructure" version = "0.12.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f36bdaa60a83aca3921b5259d5400cbf5e90fc51931376a9bd4a0eb79aa7210f" dependencies = [ "proc-macro2", "quote", "syn 1.0.109", "unicode-xid", ] [[package]] name = "synstructure" version = "0.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c8af7666ab7b6390ab78131fb5b0fce11d6b7a6951602017c35fa82800708971" dependencies = [ "proc-macro2", "quote", "syn 2.0.100", ] [[package]] name = "system-configuration" version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3c879d448e9d986b661742763247d3693ed13609438cf3d006f51f5368a5ba6b" dependencies = [ "bitflags 2.9.0", "core-foundation", "system-configuration-sys", ] [[package]] name = "system-configuration-sys" version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8e1d1b10ced5ca923a1fcb8d03e96b8d3268065d724548c0211415ff6ac6bac4" dependencies = [ "core-foundation-sys", "libc", ] [[package]] name = "target-lexicon" version = "0.12.16" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "61c41af27dd6d1e27b1b16b489db798443478cef1f06a660c96db617ba5de3b1" [[package]] name = "tempfile" version = "3.19.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7437ac7763b9b123ccf33c338a5cc1bac6f69b45a136c19bdd8a65e3916435bf" dependencies = [ "fastrand", "getrandom 0.3.2", "once_cell", "rustix", "windows-sys 0.59.0", ] [[package]] name = "text-size" version = "1.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f18aa187839b2bdb1ad2fa35ead8c4c2976b64e4363c386d45ac0f7ee85c9233" [[package]] name = "textwrap" version = "0.16.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c13547615a44dc9c452a8a534638acdf07120d4b6847c8178705da06306a3057" dependencies = [ "smawk", "unicode-linebreak", "unicode-width", ] [[package]] name = "thiserror" version = "2.0.12" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "567b8a2dae586314f7be2a752ec7474332959c6460e02bde30d702a66d488708" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" version = "2.0.12" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7f7cf42b4507d8ea322120659672cf1b9dbb93f8f2d4ecfd6e51350ff5b17a1d" dependencies = [ "proc-macro2", "quote", "syn 2.0.100", ] [[package]] name = "tinystr" version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9117f5d4db391c1cf6927e7bea3db74b9a1c1add8f7eda9ffd5364f40f57b82f" dependencies = [ "displaydoc", "zerovec", ] [[package]] name = "tinyvec" version = "1.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "09b3661f17e86524eccd4371ab0429194e0d7c008abb45f7a7495b1719463c71" dependencies = [ "tinyvec_macros", ] [[package]] name = "tinyvec_macros" version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] name = "tokio" version = "1.44.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e6b88822cbe49de4185e3a4cbf8321dd487cf5fe0c5c65695fef6346371e9c48" dependencies = [ "backtrace", "bytes", "libc", "mio 1.0.3", "pin-project-lite", "socket2", "windows-sys 0.52.0", ] [[package]] name = "tokio-native-tls" version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bbae76ab933c85776efabc971569dd6119c580d8f5d448769dec1764bf796ef2" dependencies = [ "native-tls", "tokio", ] [[package]] name = "tokio-rustls" version = "0.26.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8e727b36a1a0e8b74c376ac2211e40c2c8af09fb4013c60d910495810f008e9b" dependencies = [ "rustls", "tokio", ] [[package]] name = "tokio-util" version = "0.7.14" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6b9590b93e6fcc1739458317cccd391ad3955e2bde8913edf6f95f9e65a8f034" dependencies = [ "bytes", "futures-core", "futures-sink", "pin-project-lite", "tokio", ] [[package]] name = "toml_datetime" version = "0.6.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0dd7358ecb8fc2f8d014bf86f6f638ce72ba252a2c3a2572f2a795f1d23efb41" [[package]] name = "toml_edit" version = "0.22.24" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "17b4795ff5edd201c7cd6dca065ae59972ce77d1b80fa0a84d94950ece7d1474" dependencies = [ "indexmap", "toml_datetime", "winnow", ] [[package]] name = "tower" version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d039ad9159c98b70ecfd540b2573b97f7f52c3e8d9f8ad57a24b916a536975f9" dependencies = [ "futures-core", "futures-util", "pin-project-lite", "sync_wrapper", "tokio", "tower-layer", "tower-service", ] [[package]] name = "tower-layer" version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "121c2a6cda46980bb0fcd1647ffaf6cd3fc79a013de288782836f6df9c48780e" [[package]] name = "tower-service" version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8df9b6e13f2d32c91b9bd719c00d1958837bc7dec474d94952798cc8e69eeec3" [[package]] name = "tracing" version = "0.1.41" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "784e0ac535deb450455cbfa28a6f0df145ea1bb7ae51b821cf5e7927fdcfbdd0" dependencies = [ "log", "pin-project-lite", "tracing-attributes", "tracing-core", ] [[package]] name = "tracing-attributes" version = "0.1.28" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "395ae124c09f9e6918a2310af6038fba074bcf474ac352496d5910dd59a2226d" dependencies = [ "proc-macro2", "quote", "syn 2.0.100", ] [[package]] name = "tracing-core" version = "0.1.33" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e672c95779cf947c5311f83787af4fa8fffd12fb27e4993211a84bdfd9610f9c" dependencies = [ "once_cell", ] [[package]] name = "try-lock" version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b" [[package]] name = "typenum" version = "1.18.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1dccffe3ce07af9386bfd29e80c0ab1a8205a2fc34e4bcd40364df902cfa8f3f" [[package]] name = "unicode-bidi" version = "0.3.18" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5c1cb5db39152898a79168971543b1cb5020dff7fe43c8dc468b0885f5e29df5" [[package]] name = "unicode-ident" version = "1.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5a5f39404a5da50712a4c1eecf25e90dd62b613502b7e925fd4e4d19b5c96512" [[package]] name = "unicode-linebreak" version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3b09c83c3c29d37506a3e260c08c03743a6bb66a9cd432c6934ab501a190571f" [[package]] name = "unicode-normalization" version = "0.1.24" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5033c97c4262335cded6d6fc3e5c18ab755e1a3dc96376350f3d8e9f009ad956" dependencies = [ "tinyvec", ] [[package]] name = "unicode-properties" version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e70f2a8b45122e719eb623c01822704c4e0907e7e426a05927e1a1cfff5b75d0" [[package]] name = "unicode-width" version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1fc81956842c57dac11422a97c3b8195a1ff727f06e85c84ed2e8aa277c9a0fd" [[package]] name = "unicode-xid" version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ebc1c04c71510c7f702b52b7c350734c9ff1295c464a03335b00bb84fc54f853" [[package]] name = "unindent" version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7264e107f553ccae879d21fbea1d6724ac785e8c3bfc762137959b5802826ef3" [[package]] name = "untrusted" version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" [[package]] name = "url" version = "2.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "32f8b686cadd1473f4bd0117a5d28d36b1ade384ea9b5069a1c40aefed7fda60" dependencies = [ "form_urlencoded", "idna", "percent-encoding", "serde", ] [[package]] name = "utf16_iter" version = "1.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c8232dd3cdaed5356e0f716d285e4b40b932ac434100fe9b7e0e8e935b9e6246" [[package]] name = "utf8_iter" version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b6c140620e7ffbb22c2dee59cafe6084a59b5ffc27a8859a5f0d494b5d52b6be" [[package]] name = "utf8parse" version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" [[package]] name = "vcpkg" version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" [[package]] name = "version_check" version = "0.9.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" [[package]] name = "walkdir" version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "29790946404f91d9c5d06f9874efddea1dc06c5efe94541a7d6863108e3a5e4b" dependencies = [ "same-file", "winapi-util", ] [[package]] name = "want" version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bfa7760aed19e106de2c7c0b581b509f2f25d3dacaf737cb82ac61bc6d760b0e" dependencies = [ "try-lock", ] [[package]] name = "wasi" version = "0.11.0+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" [[package]] name = "wasi" version = "0.14.2+wasi-0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9683f9a5a998d873c0d21fcbe3c083009670149a8fab228644b8bd36b2c48cb3" dependencies = [ "wit-bindgen-rt", ] [[package]] name = "wasite" version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b8dad83b4f25e74f184f64c43b150b91efe7647395b42289f38e50566d82855b" [[package]] name = "wasm-bindgen" version = "0.2.100" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1edc8929d7499fc4e8f0be2262a241556cfc54a0bea223790e71446f2aab1ef5" dependencies = [ "cfg-if", "once_cell", "rustversion", "wasm-bindgen-macro", ] [[package]] name = "wasm-bindgen-backend" version = "0.2.100" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2f0a0651a5c2bc21487bde11ee802ccaf4c51935d0d3d42a6101f98161700bc6" dependencies = [ "bumpalo", "log", "proc-macro2", "quote", "syn 2.0.100", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-futures" version = "0.4.50" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "555d470ec0bc3bb57890405e5d4322cc9ea83cebb085523ced7be4144dac1e61" dependencies = [ "cfg-if", "js-sys", "once_cell", "wasm-bindgen", "web-sys", ] [[package]] name = "wasm-bindgen-macro" version = "0.2.100" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7fe63fc6d09ed3792bd0897b314f53de8e16568c2b3f7982f468c0bf9bd0b407" dependencies = [ "quote", "wasm-bindgen-macro-support", ] [[package]] name = "wasm-bindgen-macro-support" version = "0.2.100" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8ae87ea40c9f689fc23f209965b6fb8a99ad69aeeb0231408be24920604395de" dependencies = [ "proc-macro2", "quote", "syn 2.0.100", "wasm-bindgen-backend", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-shared" version = "0.2.100" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1a05d73b933a847d6cccdda8f838a22ff101ad9bf93e33684f39c1f5f0eece3d" dependencies = [ "unicode-ident", ] [[package]] name = "web-sys" version = "0.3.77" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "33b6dd2ef9186f1f2072e409e99cd22a975331a6b3591b12c764e0e55c60d5d2" dependencies = [ "js-sys", "wasm-bindgen", ] [[package]] name = "whoami" version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6994d13118ab492c3c80c1f81928718159254c53c472bf9ce36f8dae4add02a7" dependencies = [ "redox_syscall", "wasite", ] [[package]] name = "winapi-util" version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cf221c93e13a30d793f7645a0e7762c55d169dbb0a49671918a2319d289b10bb" dependencies = [ "windows-sys 0.59.0", ] [[package]] name = "windows-core" version = "0.61.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4763c1de310c86d75a878046489e2e5ba02c649d185f21c67d4cf8a56d098980" dependencies = [ "windows-implement", "windows-interface", "windows-link", "windows-result", "windows-strings 0.4.0", ] [[package]] name = "windows-implement" version = "0.60.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a47fddd13af08290e67f4acabf4b459f647552718f683a7b415d290ac744a836" dependencies = [ "proc-macro2", "quote", "syn 2.0.100", ] [[package]] name = "windows-interface" version = "0.59.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bd9211b69f8dcdfa817bfd14bf1c97c9188afa36f4750130fcdf3f400eca9fa8" dependencies = [ "proc-macro2", "quote", "syn 2.0.100", ] [[package]] name = "windows-link" version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "76840935b766e1b0a05c0066835fb9ec80071d4c09a16f6bd5f7e655e3c14c38" [[package]] name = "windows-registry" version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4286ad90ddb45071efd1a66dfa43eb02dd0dfbae1545ad6cc3c51cf34d7e8ba3" dependencies = [ "windows-result", "windows-strings 0.3.1", "windows-targets 0.53.0", ] [[package]] name = "windows-result" version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c64fd11a4fd95df68efcfee5f44a294fe71b8bc6a91993e2791938abcc712252" dependencies = [ "windows-link", ] [[package]] name = "windows-strings" version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "87fa48cc5d406560701792be122a10132491cff9d0aeb23583cc2dcafc847319" dependencies = [ "windows-link", ] [[package]] name = "windows-strings" version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7a2ba9642430ee452d5a7aa78d72907ebe8cfda358e8cb7918a2050581322f97" dependencies = [ "windows-link", ] [[package]] name = "windows-sys" version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" dependencies = [ "windows-targets 0.48.5", ] [[package]] name = "windows-sys" version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" dependencies = [ "windows-targets 0.52.6", ] [[package]] name = "windows-sys" version = "0.59.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" dependencies = [ "windows-targets 0.52.6", ] [[package]] name = "windows-targets" version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c" dependencies = [ "windows_aarch64_gnullvm 0.48.5", "windows_aarch64_msvc 0.48.5", "windows_i686_gnu 0.48.5", "windows_i686_msvc 0.48.5", "windows_x86_64_gnu 0.48.5", "windows_x86_64_gnullvm 0.48.5", "windows_x86_64_msvc 0.48.5", ] [[package]] name = "windows-targets" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" dependencies = [ "windows_aarch64_gnullvm 0.52.6", "windows_aarch64_msvc 0.52.6", "windows_i686_gnu 0.52.6", "windows_i686_gnullvm 0.52.6", "windows_i686_msvc 0.52.6", "windows_x86_64_gnu 0.52.6", "windows_x86_64_gnullvm 0.52.6", "windows_x86_64_msvc 0.52.6", ] [[package]] name = "windows-targets" version = "0.53.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b1e4c7e8ceaaf9cb7d7507c974735728ab453b67ef8f18febdd7c11fe59dca8b" dependencies = [ "windows_aarch64_gnullvm 0.53.0", "windows_aarch64_msvc 0.53.0", "windows_i686_gnu 0.53.0", "windows_i686_gnullvm 0.53.0", "windows_i686_msvc 0.53.0", "windows_x86_64_gnu 0.53.0", "windows_x86_64_gnullvm 0.53.0", "windows_x86_64_msvc 0.53.0", ] [[package]] name = "windows_aarch64_gnullvm" version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" [[package]] name = "windows_aarch64_gnullvm" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" [[package]] name = "windows_aarch64_gnullvm" version = "0.53.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "86b8d5f90ddd19cb4a147a5fa63ca848db3df085e25fee3cc10b39b6eebae764" [[package]] name = "windows_aarch64_msvc" version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" [[package]] name = "windows_aarch64_msvc" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" [[package]] name = "windows_aarch64_msvc" version = "0.53.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c7651a1f62a11b8cbd5e0d42526e55f2c99886c77e007179efff86c2b137e66c" [[package]] name = "windows_i686_gnu" version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" [[package]] name = "windows_i686_gnu" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" [[package]] name = "windows_i686_gnu" version = "0.53.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c1dc67659d35f387f5f6c479dc4e28f1d4bb90ddd1a5d3da2e5d97b42d6272c3" [[package]] name = "windows_i686_gnullvm" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" [[package]] name = "windows_i686_gnullvm" version = "0.53.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9ce6ccbdedbf6d6354471319e781c0dfef054c81fbc7cf83f338a4296c0cae11" [[package]] name = "windows_i686_msvc" version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" [[package]] name = "windows_i686_msvc" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" [[package]] name = "windows_i686_msvc" version = "0.53.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "581fee95406bb13382d2f65cd4a908ca7b1e4c2f1917f143ba16efe98a589b5d" [[package]] name = "windows_x86_64_gnu" version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" [[package]] name = "windows_x86_64_gnu" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" [[package]] name = "windows_x86_64_gnu" version = "0.53.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2e55b5ac9ea33f2fc1716d1742db15574fd6fc8dadc51caab1c16a3d3b4190ba" [[package]] name = "windows_x86_64_gnullvm" version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" [[package]] name = "windows_x86_64_gnullvm" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" [[package]] name = "windows_x86_64_gnullvm" version = "0.53.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0a6e035dd0599267ce1ee132e51c27dd29437f63325753051e71dd9e42406c57" [[package]] name = "windows_x86_64_msvc" version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" [[package]] name = "windows_x86_64_msvc" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" [[package]] name = "windows_x86_64_msvc" version = "0.53.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "271414315aff87387382ec3d271b52d7ae78726f5d44ac98b4f4030c91880486" [[package]] name = "winnow" version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "63d3fcd9bba44b03821e7d699eeee959f3126dcc4aa8e4ae18ec617c2a5cea10" dependencies = [ "memchr", ] [[package]] name = "wit-bindgen-rt" version = "0.39.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6f42320e61fe2cfd34354ecb597f86f413484a798ba44a8ca1165c58d42da6c1" dependencies = [ "bitflags 2.9.0", ] [[package]] name = "write16" version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d1890f4022759daae28ed4fe62859b1236caebfc61ede2f63ed4e695f3f6d936" [[package]] name = "writeable" version = "0.5.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1e9df38ee2d2c3c5948ea468a8406ff0db0b29ae1ffde1bcf20ef305bcc95c51" [[package]] name = "yoke" version = "0.7.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "120e6aef9aa629e3d4f52dc8cc43a015c7724194c97dfaf45180d2daf2b77f40" dependencies = [ "serde", "stable_deref_trait", "yoke-derive", "zerofrom", ] [[package]] name = "yoke-derive" version = "0.7.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2380878cad4ac9aac1e2435f3eb4020e8374b5f13c296cb75b4620ff8e229154" dependencies = [ "proc-macro2", "quote", "syn 2.0.100", "synstructure 0.13.1", ] [[package]] name = "zerocopy" version = "0.8.24" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2586fea28e186957ef732a5f8b3be2da217d65c5969d4b1e17f973ebbe876879" dependencies = [ "zerocopy-derive", ] [[package]] name = "zerocopy-derive" version = "0.8.24" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a996a8f63c5c4448cd959ac1bab0aaa3306ccfd060472f85943ee0750f0169be" dependencies = [ "proc-macro2", "quote", "syn 2.0.100", ] [[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 2.0.100", "synstructure 0.13.1", ] [[package]] name = "zeroize" version = "1.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ced3678a2879b30306d323f4542626697a464a97c0a07c9aebf7ebca65cd4dde" [[package]] name = "zerovec" version = "0.10.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "aa2b893d79df23bfb12d5461018d408ea19dfafe76c2c7ef6d4eba614f8ff079" dependencies = [ "yoke", "zerofrom", "zerovec-derive", ] [[package]] name = "zerovec-derive" version = "0.10.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6eafa6dfb17584ea3e2bd6e76e0cc15ad7af12b09abdd1ca55961bed9b1063c6" dependencies = [ "proc-macro2", "quote", "syn 2.0.100", ] debian-analyzer-0.158.27/Cargo.toml0000644000000064700000000000100123520ustar # 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 = "debian-analyzer" version = "0.158.27" authors = ["Jelmer Vernooij "] build = "build.rs" autolib = false autobins = false autoexamples = false autotests = false autobenches = false description = "Debian analyzer" homepage = "https://salsa.debian.org/jelmer/lintian-brush" documentation = "https://docs.rs/debian-analyzer" readme = false license = "GPL-2.0+" repository = "https://salsa.debian.org/jelmer/lintian-brush.git" resolver = "1" [features] cli = [ "dep:clap", "dep:env_logger", ] default = [ "python", "merge3", ] merge3 = ["dep:merge3"] python = [] svp = ["dep:svp-client"] udd = ["dep:sqlx"] [lib] name = "debian_analyzer" path = "src/lib.rs" [[bin]] name = "deb-vcs-publish" path = "src/bin/deb-vcs-publish.rs" required-features = ["cli"] [[bin]] name = "detect-changelog-behaviour" path = "src/bin/detect-changelog-behaviour.rs" required-features = ["cli"] [dependencies.breezyshim] version = ">=0.1.205" features = [ "dirty-tracker", "debian", ] [dependencies.chrono] version = ">=0.4" features = ["serde"] [dependencies.clap] version = "4,<5" features = [ "derive", "env", "suggestions", "cargo", "string", ] optional = true [dependencies.configparser] version = "3" [dependencies.deb822-lossless] version = "0.2" [dependencies.debian-changelog] version = "0.2" [dependencies.debian-control] version = ">=0.1.37" [dependencies.debian-copyright] version = ">=0.1.26" [dependencies.debversion] version = ">=0.3.0" features = [ "serde", "python-debian", ] [dependencies.dep3] version = "0.1.0" [dependencies.difflib] version = "0.4.0" [dependencies.distro-info] version = ">=0.4.0" [dependencies.env_logger] version = ">=0.10" optional = true [dependencies.filetime] version = "0.2" [dependencies.hex] version = "0.4.3" [dependencies.lazy-regex] version = ">=2" [dependencies.lazy_static] version = "1" [dependencies.log] version = "0.4" [dependencies.makefile-lossless] version = "0.2.0" [dependencies.maplit] version = "1.0.2" [dependencies.merge3] version = "0.2" optional = true [dependencies.patchkit] version = "0.2.1" [dependencies.pyo3] version = ">=0.22,<0.24" features = [ "serde", "chrono", ] [dependencies.reqwest] version = ">=0.11" features = [ "blocking", "json", ] [dependencies.semver] version = "1" [dependencies.serde] version = "1" features = ["derive"] [dependencies.serde_json] version = "1" [dependencies.sha1] version = "0.10.6" [dependencies.sqlx] version = ">=0.8" features = ["postgres"] optional = true [dependencies.svp-client] version = "0.2.0" optional = true [dependencies.tempfile] version = "3" [dependencies.toml_edit] version = ">=0.22" [dependencies.url] version = "2" [dev-dependencies.serial_test] version = ">=2" [build-dependencies.quote] version = "1.0.37" [build-dependencies.serde_json] version = "1" debian-analyzer-0.158.27/Cargo.toml.orig000064400000000000000000000041421046102023000160250ustar 00000000000000[package] name = "debian-analyzer" version = "0.158.27" authors = [ "Jelmer Vernooij "] edition = "2021" license = "GPL-2.0+" description = "Debian analyzer" repository = "https://salsa.debian.org/jelmer/lintian-brush.git" homepage = "https://salsa.debian.org/jelmer/lintian-brush" documentation = "https://docs.rs/debian-analyzer" [dependencies] pyo3 = { workspace = true, features = ["serde", "chrono"] } debversion = { workspace = true, features = ["serde", "python-debian"] } log = { workspace = true } lazy-regex.workspace = true serde = { workspace = true, features = ["derive"] } breezyshim = { workspace = true, features = ["debian"] } configparser.workspace = true clap = { workspace = true, features = ["derive", "env", "suggestions", "cargo", "string"], optional = true } env_logger = { workspace = true, optional = true } serde_json.workspace = true chrono = { workspace = true, features = ["serde"] } distro-info = { version = ">=0.4.0" } url = { workspace = true } tempfile.workspace = true maplit = "1.0.2" lazy_static = { workspace = true } debian-changelog = { workspace = true } debian-control = { workspace = true } debian-copyright = { workspace = true } makefile-lossless = "0.2.0" patchkit = "0.2.1" dep3 = "0.1.0" reqwest = { workspace = true, features = ["blocking", "json"] } merge3 = { version = "0.2", optional = true } difflib = "0.4.0" deb822-lossless = { workspace = true } toml_edit = { workspace = true } semver = { workspace = true } sqlx = { workspace = true, optional = true, features = ["postgres"] } filetime = "0.2" sha1 = "0.10.6" hex = "0.4.3" svp-client = { workspace = true, optional = true } [features] svp = ["dep:svp-client"] default = ["python", "merge3"] python = [] cli = ["dep:clap", "dep:env_logger"] merge3 = ["dep:merge3"] udd = ["dep:sqlx"] [lib] [[bin]] name = "detect-changelog-behaviour" path = "src/bin/detect-changelog-behaviour.rs" required-features = ["cli"] [[bin]] name = "deb-vcs-publish" path = "src/bin/deb-vcs-publish.rs" required-features = ["cli"] [build-dependencies] quote = "1.0.37" serde_json.workspace = true [dev-dependencies] serial_test = ">=2" debian-analyzer-0.158.27/build.rs000064400000000000000000000032501046102023000146020ustar 00000000000000use quote::quote; use std::path::PathBuf; fn main() { let manifest_dir = PathBuf::from(std::env::var("CARGO_MANIFEST_DIR").unwrap()); let path = manifest_dir.join("key-package-versions.json"); println!("cargo:rerun-if-changed={}", path.display()); let data: serde_json::Value = serde_json::from_reader(std::fs::File::open(path).unwrap()).unwrap(); let out_dir = PathBuf::from(std::env::var("OUT_DIR").unwrap()); let path = out_dir.join("key_package_versions.rs"); let mut file = std::fs::File::create(path).unwrap(); for (key, versions) in data.as_object().unwrap() { let key = key.to_string(); let versions = versions .as_object() .unwrap() .iter() .map(|(k, v)| (k.to_string(), v.as_str().unwrap().to_string())) .map(|(k, v)| { let k = k.as_str(); let v = v.as_str(); quote! { map.insert(#k, #v.parse::().unwrap()); } }) .collect::>(); let key = quote::format_ident!("{}_versions", key); use std::io::Write; let code = quote! { lazy_static::lazy_static! { /// A map of key package versions for the package `#key`. #[allow(non_upper_case_globals)] pub static ref #key: std::collections::HashMap<&'static str, debversion::Version> = { let mut map = std::collections::HashMap::new(); #(#versions)* map }; } }; writeln!(file, "{}", code).unwrap(); } } debian-analyzer-0.158.27/key-package-versions.json000064400000000000000000000102101046102023000200510ustar 00000000000000{ "debhelper": { "artful": "10.7.2ubuntu2", "bionic": "11.1.6ubuntu1", "bookworm": "13.11.4", "bookworm-backports": "13.23~bpo12+1", "breezy": "4.9.5ubuntu1", "bullseye": "13.3.4", "bullseye-backports": "13.11.1~bpo11+1", "buster": "12.1.1", "buster-backports": "13.3.3~bpo10+1", "cosmic": "11.3.2ubuntu1", "dapper": "5.0.7ubuntu13", "disco": "12ubuntu1", "edgy": "5.0.37.3ubuntu4", "eoan": "12.6.1ubuntu2", "feisty": "5.0.42ubuntu1", "focal": "12.10ubuntu1", "groovy": "13.2.1ubuntu1", "gutsy": "5.0.51ubuntu3", "hardy": "6.0.4ubuntu1", "hirsute": "13.3.4ubuntu1", "hoary": "4.2.28ubuntu4", "impish": "13.3.4ubuntu2", "intrepid": "7.0.13ubuntu1", "jammy": "13.6ubuntu1", "jaunty": "7.0.17ubuntu4", "jessie": "9.20150101+deb8u2", "jessie-kfreebsd-security": "9.20150101+deb8u2", "jessie-security": "9.20150101+deb8u2", "karmic": "7.3.15ubuntu3", "kinetic": "13.9.1ubuntu1", "lucid": "7.4.15ubuntu1", "lunar": "13.11.4ubuntu3", "mantic": "13.11.6ubuntu1", "maverick": "8.0.0ubuntu1", "natty": "8.1.2ubuntu4", "noble": "13.14.1ubuntu5", "oneiric": "8.9.0ubuntu1", "oracular": "13.18ubuntu2", "plucky": "13.24.1ubuntu2", "precise": "9.20120115ubuntu3", "quantal": "9.20120608ubuntu1", "raring": "9.20120909ubuntu1", "saucy": "9.20130630ubuntu1", "sid": "13.24.2", "squeeze": "8.0.0", "stretch": "10.2.5", "stretch-backports": "12.1.1~bpo9+1", "trixie": "13.24.2", "trusty": "9.20131227ubuntu1", "utopic": "9.20140613ubuntu2", "vivid": "9.20150101ubuntu1", "warty": "4.2.11ubuntu2", "wheezy": "9.20120909", "wily": "9.20150811ubuntu2", "xenial": "9.20160115ubuntu3", "yakkety": "10ubuntu1", "zesty": "10.2.2ubuntu1" }, "dpkg": { "artful": "1.18.24ubuntu1", "bionic": "1.19.0.5ubuntu2", "bookworm": "1.21.22", "breezy": "1.13.10ubuntu4", "bullseye": "1.20.13", "bullseye-proposed-updates": "1.20.12", "bullseye-security": "1.20.10", "buster": "1.19.8", "buster-proposed-updates": "1.19.8", "buster-security": "1.19.8", "cosmic": "1.19.0.5ubuntu5", "dapper": "1.13.11ubuntu6", "disco": "1.19.6ubuntu1", "edgy": "1.13.22ubuntu7", "eoan": "1.19.7ubuntu2", "feisty": "1.13.24ubuntu6", "focal": "1.19.7ubuntu3", "groovy": "1.20.5ubuntu2", "gutsy": "1.14.5ubuntu16", "hardy": "1.14.16.6ubuntu3", "hirsute": "1.20.7.1ubuntu4", "hoary": "1.10.27ubuntu1", "impish": "1.20.9ubuntu2", "intrepid": "1.14.20ubuntu6", "jammy": "1.21.1ubuntu2", "jaunty": "1.14.24ubuntu1", "jessie": "1.17.27", "jessie-kfreebsd-security": "1.17.26", "jessie-security": "1.17.26", "karmic": "1.15.4ubuntu2", "kinetic": "1.21.9ubuntu1", "lucid": "1.15.5.6ubuntu4", "lunar": "1.21.19ubuntu3", "mantic": "1.22.0ubuntu1", "maverick": "1.15.8.4ubuntu3", "natty": "1.16.0~ubuntu7", "noble": "1.22.6ubuntu6", "oneiric": "1.16.0.3ubuntu5", "oracular": "1.22.11ubuntu1", "plucky": "1.22.18ubuntu2", "precise": "1.16.1.2ubuntu7", "quantal": "1.16.7ubuntu6", "raring": "1.16.10ubuntu1", "saucy": "1.16.12ubuntu1", "sid": "1.22.18", "squeeze": "1.15.11", "squeeze-security": "1.15.11", "stretch": "1.18.25", "stretch-security": "1.18.26", "trixie": "1.22.18", "trusty": "1.17.5ubuntu5", "utopic": "1.17.13ubuntu1", "vivid": "1.17.25ubuntu1", "warty": "1.10.22ubuntu2", "wheezy": "1.16.18", "wheezy-security": "1.16.17", "wily": "1.18.2ubuntu5", "xenial": "1.18.4ubuntu1", "yakkety": "1.18.10ubuntu1", "zesty": "1.18.10ubuntu2" } }debian-analyzer-0.158.27/key-package-versions.py000075500000000000000000000042041046102023000175410ustar 00000000000000#!/usr/bin/python3 import argparse import json import os from typing import Dict from debian.changelog import Version parser = argparse.ArgumentParser() parser.add_argument( "output", help="Output file", type=str, default="key-package-versions.json" ) args = parser.parse_args() KEY_PACKAGES = ("debhelper", "dpkg") DEFAULT_UDD_URL = ( "postgresql://udd-mirror:udd-mirror@udd-mirror.debian.net/udd" ) versions: Dict[str, Dict[str, str]] with open(args.output) as f: versions = json.load(f) for kp in KEY_PACKAGES: versions.setdefault(kp, {}) def update_debian(versions, key_packages): import psycopg2 conn = psycopg2.connect(os.environ.get("UDD_URL", DEFAULT_UDD_URL)) with conn.cursor() as cursor: cursor.execute( "SELECT source, release, version from sources WHERE source IN %s", (key_packages,), ) for row in cursor: versions[row[0]][row[1]] = row[2] def update_ubuntu(versions, key_packages): from launchpadlib.launchpad import Launchpad from launchpadlib.uris import LPNET_SERVICE_ROOT lp = Launchpad.login_anonymously( "lintian-brush", service_root=LPNET_SERVICE_ROOT ) ubuntu = lp.distributions["ubuntu"] archive = ubuntu.main_archive for series in ubuntu.series: print(f" .. {series.name}") for pkg in key_packages: if ( ubuntu.current_series.name != series.name and series.name in versions[pkg] ): continue ps = archive.getPublishedSources( exact_match=True, source_name=pkg, distro_series=series ) versions[pkg][series.name] = str( max( Version(p.source_package_version) for p in ps if p.pocket == "Release" ) ) print("Downloading Debian key package information") update_debian(versions, KEY_PACKAGES) print("Downloading Ubuntu key package information") update_ubuntu(versions, KEY_PACKAGES) with open(args.output, "w") as f: json.dump(versions, f, indent=4, sort_keys=True) debian-analyzer-0.158.27/src/abstract_control.rs000064400000000000000000000204301046102023000176340ustar 00000000000000//! Abstract interface for editing debian packages, whether backed by real control files or //! debcargo files. use crate::relations::ensure_relation; use breezyshim::tree::Tree; use debian_control::lossless::relations::{Entry, Relations}; use std::path::Path; /// Interface for editing debian packages, whether backed by real control files or debcargo files. pub trait AbstractControlEditor { /// Get the source package. fn source<'a>(&'a mut self) -> Option + 'a>>; /// Get the binary packages. fn binaries<'a>(&'a mut self) -> Vec>; /// Commit the changes. fn commit(&self) -> bool; /// Wrap and sort the control file. fn wrap_and_sort(&mut self); } /// An abstract source package. pub trait AbstractSource<'a> { /// Get the name of the source package. fn name(&self) -> Option; /// Ensure that a build dependency is present. fn ensure_build_dep(&mut self, dep: Entry); /// Set the maintainer of the source package. fn set_maintainer(&mut self, maintainer: &str); /// Set the uploaders of the source package. fn set_uploaders(&mut self, uploaders: &[&str]); } /// An abstract binary package. pub trait AbstractBinary { /// Get the name of the binary package. fn name(&self) -> Option; } use crate::debcargo::{DebcargoBinary, DebcargoEditor, DebcargoSource}; use debian_control::{Binary as PlainBinary, Control as PlainControl, Source as PlainSource}; impl AbstractControlEditor for DebcargoEditor { fn source<'a>(&'a mut self) -> Option + 'a>> { Some(Box::new(DebcargoEditor::source(self)) as Box>) } fn binaries<'a>(&'a mut self) -> Vec> { DebcargoEditor::binaries(self) .map(|b| Box::new(b) as Box) .collect() } fn commit(&self) -> bool { DebcargoEditor::commit(self).unwrap() } fn wrap_and_sort(&mut self) {} } impl AbstractBinary for PlainBinary { fn name(&self) -> Option { self.name() } } impl<'a> AbstractSource<'a> for PlainSource { fn name(&self) -> Option { self.name() } fn ensure_build_dep(&mut self, dep: Entry) { if let Some(mut build_deps) = self.build_depends() { ensure_relation(&mut build_deps, dep); self.set_build_depends(&build_deps); } else { self.set_build_depends(&Relations::from(vec![dep])); } } fn set_maintainer(&mut self, maintainer: &str) { (self as &mut debian_control::lossless::Source).set_maintainer(maintainer); } fn set_uploaders(&mut self, uploaders: &[&str]) { (self as &mut debian_control::lossless::Source).set_uploaders(uploaders); } } impl<'a> AbstractBinary for DebcargoBinary<'a> { fn name(&self) -> Option { Some(self.name().to_string()) } } impl<'a> AbstractSource<'a> for DebcargoSource<'a> { fn name(&self) -> Option { self.name() } fn ensure_build_dep(&mut self, dep: Entry) { // TODO: Check that it's not already there if let Some(build_deps) = self .toml_section_mut() .get_mut("build_depends") .and_then(|v| v.as_array_mut()) { build_deps.push(dep.to_string()); } } fn set_maintainer(&mut self, maintainer: &str) { (self as &mut crate::debcargo::DebcargoSource).set_maintainer(maintainer); } fn set_uploaders(&mut self, uploaders: &[&str]) { (self as &mut crate::debcargo::DebcargoSource) .set_uploaders(uploaders.iter().map(|s| s.to_string()).collect::>()); } } impl> AbstractControlEditor for E { fn source<'a>(&'a mut self) -> Option + 'a>> { PlainControl::source(self).map(|s| Box::new(s) as Box) } fn binaries<'a>(&'a mut self) -> Vec> { PlainControl::binaries(self) .map(|b| Box::new(b) as Box) .collect() } fn commit(&self) -> bool { !(self as &dyn crate::editor::Editor) .commit() .unwrap() .is_empty() } fn wrap_and_sort(&mut self) { (self as &mut dyn crate::editor::Editor).wrap_and_sort( deb822_lossless::Indentation::Spaces(4), false, None, ) } } /// Open a control file for editing. pub fn edit_control<'a>( tree: &breezyshim::workingtree::WorkingTree, subpath: &Path, ) -> Result, crate::editor::EditorError> { if tree.has_filename(&subpath.join("debian/debcargo.toml")) { Ok(Box::new(crate::debcargo::DebcargoEditor::from_directory( &tree.abspath(subpath).unwrap(), )?)) } else { let control_path = tree.abspath(&subpath.join(std::path::Path::new("debian/control"))); Ok(Box::new(crate::control::TemplatedControlEditor::open( control_path.unwrap(), )?) as Box) } } #[cfg(test)] mod tests { use super::*; use breezyshim::controldir::{create_standalone_workingtree, ControlDirFormat}; use breezyshim::tree::MutableTree; use std::path::Path; use std::str::FromStr; #[test] fn test_edit_control_debcargo() { let td = tempfile::tempdir().unwrap(); let tree = create_standalone_workingtree(td.path(), &ControlDirFormat::default()).unwrap(); // Write dummy debcargo.toml tree.mkdir(Path::new("debian")).unwrap(); std::fs::write( td.path().join("debian/debcargo.toml"), br#" maintainer = "Alice " homepage = "https://example.com" description = "Example package" "#, ) .unwrap(); std::fs::write( td.path().join("Cargo.toml"), br#" [package] name = "example" version = "0.1.0" edition = "2018" "#, ) .unwrap(); tree.add(&[(Path::new("debian")), (Path::new("debian/debcargo.toml"))]) .unwrap(); let editor = super::edit_control(&tree, Path::new("")).unwrap(); editor.commit(); } #[test] fn test_edit_control_regular() { let td = tempfile::tempdir().unwrap(); let tree = create_standalone_workingtree(td.path(), &ControlDirFormat::default()).unwrap(); // Write dummy debian/control tree.mkdir(Path::new("debian")).unwrap(); tree.put_file_bytes_non_atomic( Path::new("debian/control"), br#" Source: example Maintainer: Alice Homepage: https://example.com Package: example Architecture: any Description: Example package "#, ) .unwrap(); tree.add(&[(Path::new("debian")), (Path::new("debian/control"))]) .unwrap(); let editor = super::edit_control(&tree, Path::new("")).unwrap(); editor.commit(); } #[test] fn test_edit_source_ensure_build_depends() { let td = tempfile::tempdir().unwrap(); let tree = create_standalone_workingtree(td.path(), &ControlDirFormat::default()).unwrap(); // Write dummy debian/control tree.mkdir(Path::new("debian")).unwrap(); tree.put_file_bytes_non_atomic( Path::new("debian/control"), br#" Source: example Maintainer: Alice Build-Depends: libc6 Package: example Architecture: any Description: Example package "#, ) .unwrap(); tree.add(&[Path::new("debian/control")]).unwrap(); let mut editor = super::edit_control(&tree, Path::new("")).unwrap(); let mut source = editor.source().unwrap(); source.ensure_build_dep( debian_control::lossless::relations::Entry::from_str("libssl-dev").unwrap(), ); std::mem::drop(source); editor.commit(); let text = tree.get_file_text(Path::new("debian/control")).unwrap(); assert_eq!( std::str::from_utf8(&text).unwrap(), r#" Source: example Maintainer: Alice Build-Depends: libc6, libssl-dev Package: example Architecture: any Description: Example package "# ); } } debian-analyzer-0.158.27/src/benfile.rs000064400000000000000000000475461046102023000157160ustar 00000000000000//! File parsing for the benfile format. use std::iter::Peekable; use std::vec::IntoIter; #[derive(Debug, PartialEq, Clone)] enum Token { True, False, Not, Or, And, LParen, RParen, Field(String), Identifier(String), Regex(String), Source, Comparison(Comparison), String(String), Semicolon, Tilde, } struct Lexer<'a> { input: &'a str, } impl<'a> Lexer<'a> { pub fn new(input: &'a str) -> Self { Lexer { input } } pub fn next_token(&mut self) -> Result, String> { self.skip_whitespace(); if self.input.is_empty() { return Ok(None); } let c = self.current_char(); match c { Some('t') if self.input.starts_with("true") => { self.input = &self.input[4..]; Ok(Some(Token::True)) } Some('f') if self.input.starts_with("false") => { self.input = &self.input[5..]; Ok(Some(Token::False)) } Some('!') => { self.input = &self.input[1..]; Ok(Some(Token::Not)) } Some('|') => { self.input = &self.input[1..]; Ok(Some(Token::Or)) } Some('&') => { self.input = &self.input[1..]; Ok(Some(Token::And)) } Some('(') => { self.input = &self.input[1..]; Ok(Some(Token::LParen)) } Some(')') => { self.input = &self.input[1..]; Ok(Some(Token::RParen)) } Some('.') => { self.input = &self.input[1..]; let field = self.consume_while(Self::is_valid_field_char); Ok(Some(Token::Field(field.to_string()))) } Some('/') => { self.input = &self.input[1..]; let regex = self.consume_until('/'); self.input = &self.input[1..]; Ok(Some(Token::Regex(regex.to_string()))) } Some('"') => { self.input = &self.input[1..]; // consume until next ", but allow escaping with \ let in_escape = std::sync::atomic::AtomicBool::new(false); let string = self.consume_while(move |c| { if in_escape.swap(false, std::sync::atomic::Ordering::SeqCst) { true } else if c == '\\' { in_escape.store(true, std::sync::atomic::Ordering::SeqCst); true } else { c != '"' } }); self.input = &self.input[1..]; Ok(Some(Token::String(string.to_string()))) } Some('~') => { self.input = &self.input[1..]; Ok(Some(Token::Tilde)) } Some('<' | '>' | '=') if self.is_comparison() => { let comparison = self.consume_comparison()?; Ok(Some(Token::Comparison(comparison))) } Some('s') if self.input.starts_with("source") => { self.input = &self.input[6..]; Ok(Some(Token::Source)) } Some(';') => { self.input = &self.input[1..]; Ok(Some(Token::Semicolon)) } Some(c) if Self::is_valid_identifier_char(c) => { let identifier = self.consume_while(Self::is_valid_identifier_char); Ok(Some(Token::Identifier(identifier.to_string()))) } None => Ok(None), Some(c) => Err(format!("Unexpected character: {}", c)), } } fn is_valid_identifier_char(c: char) -> bool { c.is_alphanumeric() || c == '_' } fn is_valid_field_char(c: char) -> bool { c.is_alphanumeric() || c == '-' } fn current_char(&mut self) -> Option { self.skip_whitespace(); self.input.chars().next() } fn skip_whitespace(&mut self) { while !self.input.is_empty() && self.input.chars().next().unwrap().is_whitespace() { self.input = &self.input[1..]; } } fn consume_while(&mut self, test: F) -> &'a str where F: Fn(char) -> bool, { let mut end = 0; while !self.input.len() > end && test(self.input.chars().nth(end).unwrap()) { end += 1; } let (word, rest) = self.input.split_at(end); self.input = rest; word } fn consume_until(&mut self, end_char: char) -> &'a str { let mut end = 0; while self.input.chars().nth(end).unwrap() != end_char { end += 1; } let (word, rest) = self.input.split_at(end); self.input = rest; word } fn is_comparison(&self) -> bool { let comparisons = ["<<", "<=", "<", ">=", ">>", ">", "="]; for &comp in &comparisons { if self.input.starts_with(comp) { return true; } } false } fn consume_comparison(&mut self) -> Result { if self.input.starts_with("<<") { self.input = &self.input[2..]; Ok(Comparison::MuchLessThan) } else if self.input.starts_with("<=") { self.input = &self.input[2..]; Ok(Comparison::LessOrEqual) } else if self.input.starts_with("<") { self.input = &self.input[2..]; Ok(Comparison::LessThan) } else if self.input.starts_with(">=") { self.input = &self.input[2..]; Ok(Comparison::GreaterOrEqual) } else if self.input.starts_with(">>") { self.input = &self.input[2..]; Ok(Comparison::MuchGreaterThan) } else if self.input.starts_with(">") { self.input = &self.input[1..]; Ok(Comparison::GreaterThan) } else if self.input.starts_with("=") { self.input = &self.input[1..]; Ok(Comparison::Equal) } else { Err(format!("Expected comparison, got {}", self.input)) } } } #[derive(Debug, PartialEq, Eq, Clone)] /// The comparison operators supported by the benfile format. pub enum Comparison { /// < LessThan, /// << MuchLessThan, /// <= LessOrEqual, /// > GreaterThan, /// >> MuchGreaterThan, /// >= GreaterOrEqual, /// = Equal, } impl std::fmt::Display for Comparison { fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { match self { Comparison::LessThan => write!(f, "<"), Comparison::MuchLessThan => write!(f, "<<"), Comparison::LessOrEqual => write!(f, "<="), Comparison::GreaterThan => write!(f, ">"), Comparison::MuchGreaterThan => write!(f, ">>"), Comparison::GreaterOrEqual => write!(f, ">="), Comparison::Equal => write!(f, "="), } } } impl std::str::FromStr for Comparison { type Err = String; fn from_str(s: &str) -> Result { match s { "<" => Ok(Comparison::LessThan), "<<" => Ok(Comparison::MuchLessThan), "<=" => Ok(Comparison::LessOrEqual), ">" => Ok(Comparison::GreaterThan), ">>" => Ok(Comparison::MuchGreaterThan), ">=" => Ok(Comparison::GreaterOrEqual), "=" => Ok(Comparison::Equal), _ => Err(format!("Invalid comparison: {}", s)), } } } #[derive(PartialEq, Eq, Clone)] /// The expression types supported by the benfile format. pub enum Expr { /// true or false Bool(bool), /// ! Not(Box), /// | Or(Vec>), /// & And(Vec>), /// Field ~ /regex/ FieldRegex(String, String), /// Field ~ "string" FieldString(String, String), /// source Source, /// "" Comparison(Comparison, String), /// ~ "" FieldComparison(String, Comparison, String), /// "string" String(String), } #[derive(Debug, PartialEq, Eq)] /// An assignment in a benfile. pub struct Assignment { /// The field being assigned to. pub field: String, /// The expression being assigned. pub expr: Expr, } impl std::str::FromStr for Assignment { type Err = String; fn from_str(s: &str) -> Result { let mut lexer = Lexer::new(s); let mut tokens = vec![]; while let Some(token) = lexer.next_token()? { tokens.push(token); } let mut parser = Parser::new(tokens); let assignment = parser.parse_assignment()?; match assignment { Some(assignment) => Ok(assignment), None => Err("Expected assignment".to_string()), } } } impl std::str::FromStr for Expr { type Err = String; fn from_str(s: &str) -> Result { let mut lexer = Lexer::new(s); let mut tokens = vec![]; while let Some(token) = lexer.next_token()? { tokens.push(token); } let mut parser = Parser::new(tokens); parser.parse() } } impl std::fmt::Debug for Expr { fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { match self { Expr::Bool(b) => write!(f, "Bool({})", b), Expr::Not(expr) => write!(f, "Not({:?})", expr), Expr::Or(exprs) => write!(f, "Or({:?})", exprs), Expr::And(exprs) => write!(f, "And({:?})", exprs), Expr::FieldRegex(field, regex) => write!(f, "FieldRegex({}, {})", field, regex), Expr::FieldString(field, string) => write!(f, "FieldString({}, {})", field, string), Expr::Source => write!(f, "Source"), Expr::Comparison(comp, string) => write!(f, "Comparison({}, {})", comp, string), Expr::FieldComparison(field, comp, string) => { write!(f, "FieldComparison({}, {}, {})", field, comp, string) } Expr::String(string) => write!(f, "String({})", string), } } } struct Parser { tokens: Peekable>, } impl Parser { pub fn new(tokens: Vec) -> Self { Parser { tokens: tokens.into_iter().peekable(), } } pub fn parse_multiple(&mut self) -> Result, String> { let mut assignments = vec![]; while let Some(assignment) = self.parse_assignment()? { assignments.push(assignment); } Ok(assignments) } pub fn parse_assignment(&mut self) -> Result, String> { let field = match self.tokens.next() { Some(Token::Identifier(field)) => field, None => return Ok(None), n => { return Err(format!("Expected identifier, got {:?}", n)); } }; if self.tokens.next() != Some(Token::Comparison(Comparison::Equal)) { return Err("Expected =".to_string()); } let expr = self.parse()?; if self.tokens.next() == Some(Token::Semicolon) { Ok(Some(Assignment { field, expr })) } else { Err(format!("Expected ;, got {:?}", self.tokens.peek())) } } pub fn parse(&mut self) -> Result { let expr: Expr = match self.tokens.next() { // true Some(Token::True) => Ok(Expr::Bool(true)), // false Some(Token::False) => Ok(Expr::Bool(false)), // "string" Some(Token::String(string)) => Ok(Expr::String(string)), // ( ) Some(Token::LParen) => { let expr = self.parse()?; match self.tokens.next() { Some(Token::RParen) => Ok(expr), Some(n) => Err(format!("Expected ), got {:?}", n)), None => Err("Expected ), got end of file".to_string()), } } // ! Some(Token::Not) => Ok(Expr::Not(Box::new(self.parse()?))), Some(Token::Field(field)) => { if self.tokens.next() != Some(Token::Tilde) { return Err(format!("Expected ~, got {:?}", self.tokens.peek())); } match self.tokens.next() { // ~ /regex/ Some(Token::Regex(regex)) => Ok(Expr::FieldRegex(field, regex)), // ~ "" "" Some(Token::String(comp_str)) => { let n = self.tokens.peek().cloned(); match n { Some(Token::Comparison(comp)) => { self.tokens.next(); if let Some(Token::String(comp_str2)) = self.tokens.next() { Ok(Expr::FieldComparison(field, comp.clone(), comp_str2)) } else { Err("Expected string".to_string()) } } // ~ "string" _ => Ok(Expr::FieldString(field, comp_str)), } } _ => Err(format!( "Expected regex or string, got {:?}", self.tokens.peek() )), } } Some(Token::Source) => Ok(Expr::Source), // "" Some(Token::Comparison(comp)) => { if let Some(Token::String(comp_str)) = self.tokens.next() { Ok(Expr::Comparison(comp, comp_str)) } else { Err("Expected string".to_string()) } } n => Err(format!("Unexpected token: {:?}", n)), }?; match self.tokens.peek() { Some(&Token::And) => { let mut ands = vec![Box::new(expr)]; while self.tokens.peek() == Some(&Token::And) { self.tokens.next().unwrap(); match self.parse()? { Expr::And(new_ands) => { ands.extend(new_ands); } next_expr => { ands.push(Box::new(next_expr)); } } } Ok(Expr::And(ands)) } Some(&Token::Or) => { let mut ors = vec![Box::new(expr)]; while self.tokens.peek() == Some(&Token::Or) { self.tokens.next().unwrap(); match self.parse()? { Expr::Or(new_ors) => { ors.extend(new_ors); } next_expr => { ors.push(Box::new(next_expr)); } } } Ok(Expr::Or(ors)) } _ => Ok(expr), } } } /// Read a benfile from a reader and return a vector of assignments. pub fn read_benfile(mut reader: R) -> Result, String> { let mut text = String::new(); reader .read_to_string(&mut text) .map_err(|e| e.to_string())?; let mut lexer = Lexer::new(&text); let mut tokens = vec![]; while let Some(token) = lexer.next_token()? { tokens.push(token); } let mut parser = Parser::new(tokens); let assignments = parser.parse_multiple()?; Ok(assignments) } #[cfg(test)] mod tests { use super::*; #[test] fn test_simple_lex() { let input = r#"true & .field ~ /regex/ | .field ~ "string" << "comparison""#; let mut lexer = Lexer::new(input); let mut tokens = vec![]; while let Some(token) = lexer.next_token().unwrap() { tokens.push(token); } assert_eq!( tokens, vec![ Token::True, Token::And, Token::Field("field".to_string()), Token::Tilde, Token::Regex("regex".to_string()), Token::Or, Token::Field("field".to_string()), Token::Tilde, Token::String("string".to_string()), Token::Comparison(Comparison::MuchLessThan), Token::String("comparison".to_string()) ] ); } #[test] fn test_simple_parse() { let input = r#"true & .field ~ /regex/ | .field ~ "string" << "comparison""#; let mut lexer = Lexer::new(input); let mut tokens: Vec = vec![]; while let Some(token) = lexer.next_token().unwrap() { tokens.push(token); } let mut parser = Parser::new(tokens); assert_eq!( Ok(Expr::And(vec![ Box::new(Expr::Bool(true)), Box::new(Expr::Or(vec![ Box::new(Expr::FieldRegex("field".to_string(), "regex".to_string())), Box::new(Expr::FieldComparison( "field".to_string(), Comparison::MuchLessThan, "comparison".to_string() )) ])) ])), parser.parse() ); } #[test] fn test_parse_benfile() { let input = r###"title = "libsoup2.4 -> libsoup3"; is_affected = .build-depends ~ /libsoup2.4-dev|libsoup-gnome2.4-dev|libsoup-3.0-dev/ | .build-depends-arch ~ /libsoup2.4-dev|libsoup-gnome2.4-dev|libsoup-3.0-dev/ | .build-depends ~ /gir1.2-soup-2.4|gir1.2-soup-3.0/ | .depends ~ /gir1.2-soup-2.4/; is_good = .depends ~ /libsoup-3.0-0|gir1.2-soup-3.0/; is_bad = .depends ~ /libsoup-2.4-1|libsoup-gnome-2.4-1|gir1.2-soup-2.4/; notes = "https://bugs.debian.org/cgi-bin/pkgreport.cgi?users=pkg-gnome-maintainers@lists.alioth.debian.org&tag=libsoup2"; export = false; "###; let assignments = read_benfile(input.as_bytes()).unwrap(); assert_eq!(assignments.len(), 6); assert_eq!( assignments[0], Assignment { field: "title".to_string(), expr: Expr::String("libsoup2.4 -> libsoup3".to_string()) } ); assert_eq!( assignments[1], Assignment { field: "is_affected".to_string(), expr: Expr::Or(vec![ Box::new(Expr::FieldRegex( "build-depends".to_string(), "libsoup2.4-dev|libsoup-gnome2.4-dev|libsoup-3.0-dev".to_string() )), Box::new(Expr::FieldRegex( "build-depends-arch".to_string(), "libsoup2.4-dev|libsoup-gnome2.4-dev|libsoup-3.0-dev".to_string() )), Box::new(Expr::FieldRegex( "build-depends".to_string(), "gir1.2-soup-2.4|gir1.2-soup-3.0".to_string() )), Box::new(Expr::FieldRegex( "depends".to_string(), "gir1.2-soup-2.4".to_string() )) ]) } ); assert_eq!(assignments[4], Assignment { field: "notes".to_string(), expr: Expr::String("https://bugs.debian.org/cgi-bin/pkgreport.cgi?users=pkg-gnome-maintainers@lists.alioth.debian.org&tag=libsoup2".to_string()) } ); assert_eq!( assignments[5], Assignment { field: "export".to_string(), expr: Expr::Bool(false) } ); } } debian-analyzer-0.158.27/src/bin/deb-vcs-publish.rs000064400000000000000000000103071046102023000200320ustar 00000000000000use breezyshim::controldir::open; use breezyshim::error::Error; use breezyshim::workingtree; use clap::Parser; use debian_analyzer::publish::{create_vcs_url, update_official_vcs}; use debian_changelog::get_maintainer; use debian_analyzer::get_committer; use std::io::Write as _; #[derive(clap::Args, Clone, Debug)] #[group()] struct OutputArgs {} #[derive(Parser, Debug)] #[command(author, version)] struct Args { /// Enable debug output #[arg(long, default_value_t = false)] debug: bool, /// Print user identity that would be used when committing #[arg(long, default_value_t = false)] identity: bool, /// directory to run in #[arg(short, long, default_value = std::env::current_dir().unwrap().into_os_string(), value_name = "DIR")] directory: std::path::PathBuf, /// Do not create the repository #[arg(default_value_t = false)] no_create: bool, #[arg(default_value_t = false)] force: bool, /// Push branch #[arg(default_value_t = false)] push: bool, url: Option, } fn main() -> Result<(), Box> { let args = Args::parse(); env_logger::builder() .format(|buf, record| writeln!(buf, "{}", record.args())) .filter( None, if args.debug { log::LevelFilter::Debug } else { log::LevelFilter::Info }, ) .init(); breezyshim::init(); let (wt, subpath) = match workingtree::open_containing(&args.directory) { Ok((wt, subpath)) => (wt, subpath.display().to_string()), Err(Error::NotBranchError(_msg, _)) => { log::error!("No version control directory found (e.g. a .git directory)."); std::process::exit(1); } Err(Error::DependencyNotPresent(name, _reason)) => { log::error!( "Unable to open tree at {}: missing package {}", args.directory.display(), name ); std::process::exit(1); } Err(e) => { log::error!("Unable to open tree at {}: {}", args.directory.display(), e); std::process::exit(1); } }; if args.identity { println!("Committer identity: {}", get_committer(&wt)); let (maintainer, email) = get_maintainer().unwrap_or(("".to_string(), "".to_string())); println!("Changelog identity: {} <{}>", maintainer, email); std::process::exit(0); } let parsed_vcs = match update_official_vcs( &wt, std::path::Path::new(subpath.as_str()), args.url.as_ref(), None, None, Some(args.force), ) { Ok(o) => o, Err(e) => { log::error!("Unable to update official VCS: {}", e); std::process::exit(1); } }; let repo_url: url::Url = parsed_vcs.repo_url.parse().unwrap(); if !args.no_create { match create_vcs_url(&repo_url, parsed_vcs.branch.as_deref()) { Ok(()) => {} Err(Error::UnsupportedForge(_)) => { log::error!("Unable to find a way to create {}", repo_url); } Err(Error::ForgeProjectExists(..)) | Err(Error::AlreadyControlDir(..)) => { log::error!("Unable to create {}: already exists", repo_url); std::process::exit(1); } Err(Error::ForgeLoginRequired) => { log::error!("Unable to create {}: login required", repo_url); std::process::exit(1); } Err(e) => { log::error!("Unable to create {}: {}", repo_url, e); std::process::exit(1); } } } let controldir = open(&repo_url, None).unwrap(); let branch = match controldir.open_branch(parsed_vcs.branch.as_deref()) { Ok(branch) => branch, Err(Error::NotBranchError(_, _)) => controldir .create_branch(parsed_vcs.branch.as_deref()) .unwrap(), Err(e) => { log::error!("Unable to open or create branch: {}", e); std::process::exit(1); } }; wt.branch() .push(branch.as_ref(), false, None, None) .unwrap(); Ok(()) } debian-analyzer-0.158.27/src/bin/detect-changelog-behaviour.rs000064400000000000000000000024631046102023000222260ustar 00000000000000use breezyshim::workingtree; use clap::Parser; use std::io::Write as _; #[derive(Parser)] #[command(author, version)] struct Args { /// Be verbose #[clap(long)] verbose: bool, /// The directory to check #[clap(default_value = ".")] directory: std::path::PathBuf, } fn main() { let args = Args::parse(); env_logger::builder() .format(|buf, record| writeln!(buf, "{}", record.args())) .filter( None, if args.verbose { log::LevelFilter::Debug } else { log::LevelFilter::Info }, ) .init(); breezyshim::init(); let (wt, subpath) = workingtree::open_containing(&args.directory).unwrap(); let debian_path = if debian_analyzer::control_files_in_root(&wt, subpath.as_path()) { subpath } else { subpath.join("debian") }; let changelog_behaviour = debian_analyzer::detect_gbp_dch::guess_update_changelog(&wt, debian_path.as_path(), None); if let Some(changelog_behaviour) = changelog_behaviour { log::info!("{}", changelog_behaviour.explanation); println!("{}", changelog_behaviour.update_changelog); } else { log::info!("Unable to determine changelog updating behaviour"); std::process::exit(1) } } debian-analyzer-0.158.27/src/changelog.rs000064400000000000000000000505341046102023000162300ustar 00000000000000//! Functions for working with debian/changelog files. use crate::release_info; use breezyshim::error::Error; use breezyshim::tree::{Tree, TreeChange, WorkingTree}; use debian_changelog::ChangeLog; /// Check whether the only change in a tree is to the last changelog entry. /// /// # Arguments /// * `tree`: Tree to analyze /// * `changelog_path`: Path to the changelog file /// * `changes`: Changes in the tree pub fn only_changes_last_changelog_block<'a>( tree: &WorkingTree, basis_tree: &dyn Tree, changelog_path: &std::path::Path, changes: impl Iterator, ) -> Result { let read_lock = tree.lock_read(); let basis_lock = basis_tree.lock_read(); let mut changes_seen = false; for change in changes { if let Some(path) = change.path.1.as_ref() { if path == std::path::Path::new("") { continue; } if path == changelog_path { changes_seen = true; continue; } if !tree.has_versioned_directories() && changelog_path.starts_with(path) { // Directory leading up to changelog continue; } } // If the change is not in the changelog, it's not just a changelog change return Ok(false); } if !changes_seen { // Doesn't change the changelog at all return Ok(false); } let mut new_cl = match tree.get_file(changelog_path) { Ok(f) => ChangeLog::read(f)?, Err(Error::NoSuchFile(_)) => { return Ok(false); } Err(e) => { panic!("Error reading changelog: {}", e); } }; let mut old_cl = match basis_tree.get_file(changelog_path) { Ok(f) => ChangeLog::read(f)?, Err(Error::NoSuchFile(_)) => { return Ok(true); } Err(e) => { panic!("Error reading changelog: {}", e); } }; let first_entry = if let Some(e) = new_cl.pop_first() { e } else { // No entries return Ok(false); }; if first_entry.distributions().as_deref() != Some(&["UNRELEASED".into()]) { // Not unreleased return Ok(false); } old_cl.pop_first(); std::mem::drop(read_lock); std::mem::drop(basis_lock); Ok(new_cl.to_string() == old_cl.to_string()) } /// Find the last distribution the package was uploaded to. pub fn find_last_distribution(cl: &ChangeLog) -> Option { for block in cl.iter() { if block.is_unreleased() != Some(true) { if let Some(distributions) = block.distributions() { if distributions.len() == 1 { return Some(distributions[0].clone()); } } } } None } /// Given a tree, find the previous upload to the distribution. /// /// When e.g. Ubuntu merges from Debian they want to build with /// -vPREV_VERSION. Here's where we find that previous version. /// /// We look at the last changelog entry and find the upload target. /// We then search backwards until we find the same target. That's /// the previous version that we return. /// /// We require there to be a previous version, otherwise we throw /// an error. /// /// It's not a simple string comparison to find the same target in /// a previous version, as we should consider old series in e.g. /// Ubuntu. pub fn find_previous_upload(changelog: &ChangeLog) -> Option { let current_target = find_last_distribution(changelog)?; // multiple debian pockets with all debian releases let all_debian = crate::release_info::debian_releases() .iter() .flat_map(|r| { release_info::DEBIAN_POCKETS .iter() .map(move |t| format!("{}{}", r, t)) }) .collect::>(); let all_ubuntu = crate::release_info::ubuntu_releases() .iter() .flat_map(|r| { release_info::UBUNTU_POCKETS .iter() .map(move |t| format!("{}{}", r, t)) }) .collect::>(); let match_targets = if all_debian.contains(¤t_target) { vec![current_target] } else if all_ubuntu.contains(¤t_target) { let mut match_targets = crate::release_info::ubuntu_releases(); if current_target.contains('-') { let distro = current_target.split('-').next().unwrap(); match_targets.extend( release_info::DEBIAN_POCKETS .iter() .map(|r| format!("{}{}", r, distro)), ); } match_targets } else { // If we do not recognize the current target in order to apply special // rules to it, then just assume that only previous uploads to exactly // the same target count. vec![current_target] }; for block in changelog.iter().skip(1) { if match_targets.contains(&block.distributions().unwrap()[0]) { return block.version().clone(); } } None } #[derive(Debug)] /// Error type for find_changelog pub enum FindChangelogError { /// No changelog found in the given files MissingChangelog(Vec), /// Add a changelog at the given file AddChangelog(std::path::PathBuf), /// Error parsing the changelog ChangelogParseError(String), /// Error from breezyshim BrzError(breezyshim::error::Error), } impl std::fmt::Display for FindChangelogError { fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { match self { FindChangelogError::MissingChangelog(files) => { write!(f, "No changelog found in {:?}", files) } FindChangelogError::AddChangelog(file) => { write!(f, "Add a changelog at {:?}", file) } FindChangelogError::ChangelogParseError(e) => write!(f, "{}", e), FindChangelogError::BrzError(e) => write!(f, "{}", e), } } } impl std::error::Error for FindChangelogError {} impl From for FindChangelogError { fn from(e: breezyshim::error::Error) -> Self { FindChangelogError::BrzError(e) } } /// Find the changelog in the given tree. /// /// First looks for 'debian/changelog'. If "merge" is true will also /// look for 'changelog'. /// /// The returned changelog is created with 'allow_empty_author=True' /// as some people do this but still want to build. /// 'max_blocks' defaults to 1 to try and prevent old broken /// changelog entries from causing the command to fail. /// /// "top_level" is a subset of "merge" mode. It indicates that the /// '.bzr' dir is at the same level as 'changelog' etc., rather /// than being at the same level as 'debian/'. /// /// # Arguments /// * `tree`: Tree to look in /// * `subpath`: Path to the changelog file /// * `merge`: Whether this is a "merge" package /// /// # Returns /// * (changelog, top_level) where changelog is the Changelog, /// and top_level is a boolean indicating whether the file is /// located at 'changelog' (rather than 'debian/changelog') if /// merge was given, False otherwise. pub fn find_changelog( tree: &dyn Tree, subpath: &std::path::Path, merge: Option, ) -> Result<(ChangeLog, bool), FindChangelogError> { let mut top_level = false; let lock = tree.lock_read(); let mut changelog_file = subpath.join("debian/changelog"); if !tree.has_filename(&changelog_file) { let mut checked_files = vec![changelog_file.clone()]; let changelog_file = if merge.unwrap_or(false) { // Assume LarstiQ's layout (.bzr in debian/) let changelog_file = subpath.join("changelog"); top_level = true; if !tree.has_filename(&changelog_file) { checked_files.push(changelog_file); None } else { Some(changelog_file) } } else { None }; if changelog_file.is_none() { return Err(FindChangelogError::MissingChangelog(checked_files)); } } else if merge.unwrap_or(true) && tree.has_filename(&subpath.join("changelog")) { // If it is a "top_level" package and debian is a symlink to // "." then it will have found debian/changelog. Try and detect // this. let debian_file = subpath.join("debian"); if tree.is_versioned(&debian_file) && tree.kind(&debian_file)? == breezyshim::tree::Kind::Symlink && tree.get_symlink_target(&debian_file)?.as_path() == std::path::Path::new(".") { changelog_file = "changelog".into(); top_level = true; } } log::debug!( "Using '{}' to get package information", changelog_file.display() ); if !tree.is_versioned(&changelog_file) { return Err(FindChangelogError::AddChangelog(changelog_file)); } let contents = tree.get_file_text(&changelog_file)?; std::mem::drop(lock); let changelog = ChangeLog::read_relaxed(contents.as_slice()).unwrap(); Ok((changelog, top_level)) } #[cfg(test)] mod tests { use super::*; pub const COMMITTER: &str = "Test User "; #[test] fn test_find_previous_upload() { let cl = r#"test (1.0-1) unstable; urgency=medium * Initial release. -- Test User Fri, 01 Jan 2021 00:00:00 +0000 "# .parse() .unwrap(); assert_eq!(super::find_previous_upload(&cl), None); let cl = r#"test (1.0-1) unstable; urgency=medium * More change. -- Test User Fri, 01 Jan 2021 00:00:00 +0000 test (1.0-0) unstable; urgency=medium * Initial release. -- Test User Fri, 01 Jan 2021 00:00:00 +0000 "# .parse() .unwrap(); assert_eq!( super::find_previous_upload(&cl), Some("1.0-0".parse().unwrap()) ); } mod test_only_changes_last_changelog_block { use super::*; use breezyshim::controldir::{create_standalone_workingtree, ControlDirFormat}; use breezyshim::tree::Path; use breezyshim::tree::Tree; fn make_package_tree(p: &std::path::Path) -> breezyshim::tree::WorkingTree { let tree = create_standalone_workingtree(p, &ControlDirFormat::default()).unwrap(); std::fs::create_dir_all(p.join("debian")).unwrap(); std::fs::write( p.join("debian/control"), r###"Source: blah Vcs-Git: https://example.com/blah Testsuite: autopkgtest Binary: blah Arch: all "###, ) .unwrap(); std::fs::write( p.join("debian/changelog"), r###"blah (0.2) UNRELEASED; urgency=medium * And a change. -- Blah Sat, 13 Oct 2018 11:21:39 +0100 blah (0.1) unstable; urgency=medium * Initial release. (Closes: #911016) -- Blah Sat, 13 Oct 2018 11:21:39 +0100 "###, ) .unwrap(); tree.add(&[ Path::new("debian"), Path::new("debian/changelog"), Path::new("debian/control"), ]) .unwrap(); tree.build_commit() .message("Initial thingy.") .committer(COMMITTER) .commit() .unwrap(); tree } #[test] fn test_no_changes() { let td = tempfile::tempdir().unwrap(); let tree = make_package_tree(td.path()); let basis_tree = tree.basis_tree().unwrap(); let lock_read = tree.lock_read(); let basis_lock_read = basis_tree.lock_read(); let changes = tree .iter_changes(&basis_tree, None, None, None) .unwrap() .collect::, _>>() .unwrap(); assert!(!only_changes_last_changelog_block( &tree, &tree.basis_tree().unwrap(), Path::new("debian/changelog"), changes.iter() ) .unwrap()); std::mem::drop(basis_lock_read); std::mem::drop(lock_read); } #[test] fn test_other_change() { let td = tempfile::tempdir().unwrap(); let tree = make_package_tree(td.path()); std::fs::write( td.path().join("debian/control"), r###"Source: blah Vcs-Bzr: https://example.com/blah Testsuite: autopkgtest Binary: blah Arch: all "###, ) .unwrap(); let basis_tree = tree.basis_tree().unwrap(); let lock_read = tree.lock_read(); let basis_lock_read = basis_tree.lock_read(); let changes = tree .iter_changes(&basis_tree, None, None, None) .unwrap() .collect::, _>>() .unwrap(); assert!(!only_changes_last_changelog_block( &tree, &tree.basis_tree().unwrap(), Path::new("debian/changelog"), changes.iter() ) .unwrap()); std::mem::drop(basis_lock_read); std::mem::drop(lock_read); } #[test] fn test_other_changes() { let td = tempfile::tempdir().unwrap(); let tree = make_package_tree(td.path()); std::fs::write( td.path().join("debian/control"), r###"Source: blah Vcs-Bzr: https://example.com/blah Testsuite: autopkgtest Binary: blah Arch: all "###, ) .unwrap(); std::fs::write( td.path().join("debian/changelog"), r###"blah (0.1) UNRELEASED; urgency=medium * Initial release. (Closes: #911016) * Some other change. -- Blah Sat, 13 Oct 2018 11:21:39 +0100 "###, ) .unwrap(); let basis_tree = tree.basis_tree().unwrap(); let lock_read = tree.lock_read(); let basis_lock_read = basis_tree.lock_read(); let changes = tree .iter_changes(&basis_tree, None, None, None) .unwrap() .collect::, _>>() .unwrap(); assert!(!only_changes_last_changelog_block( &tree, &tree.basis_tree().unwrap(), Path::new("debian/changelog"), changes.iter() ) .unwrap()); std::mem::drop(basis_lock_read); std::mem::drop(lock_read); } #[test] fn test_changes_to_other_changelog_entries() { let td = tempfile::tempdir().unwrap(); let tree = make_package_tree(td.path()); std::fs::write( td.path().join("debian/changelog"), r###"blah (0.2) UNRELEASED; urgency=medium * debian/changelog: And a change. -- Blah Sat, 13 Oct 2018 11:21:39 +0100 blah (0.1) unstable; urgency=medium * debian/changelog: Initial release. (Closes: #911016) -- Blah Sat, 13 Oct 2018 11:21:39 +0100 "###, ) .unwrap(); let basis_tree = tree.basis_tree().unwrap(); let lock_read = tree.lock_read(); let basis_lock_read = basis_tree.lock_read(); let changes = tree .iter_changes(&basis_tree, None, None, None) .unwrap() .collect::, _>>() .unwrap(); assert!(!only_changes_last_changelog_block( &tree, &tree.basis_tree().unwrap(), Path::new("debian/changelog"), changes.iter() ) .unwrap()); std::mem::drop(basis_lock_read); std::mem::drop(lock_read); } #[test] fn test_changes_to_last_only() { let td = tempfile::tempdir().unwrap(); let tree = make_package_tree(td.path()); std::fs::write( td.path().join("debian/changelog"), r###"blah (0.2) UNRELEASED; urgency=medium * And a change. * Not a team upload. -- Blah Sat, 13 Oct 2018 11:21:39 +0100 blah (0.1) unstable; urgency=medium * Initial release. (Closes: #911016) -- Blah Sat, 13 Oct 2018 11:21:39 +0100 "###, ) .unwrap(); let basis_tree = tree.basis_tree().unwrap(); let lock_read = tree.lock_read(); let basis_lock_read = basis_tree.lock_read(); let changes = tree .iter_changes(&basis_tree, None, None, None) .unwrap() .collect::, _>>() .unwrap(); assert!(only_changes_last_changelog_block( &tree, &tree.basis_tree().unwrap(), Path::new("debian/changelog"), changes.iter() ) .unwrap()); std::mem::drop(basis_lock_read); std::mem::drop(lock_read); } #[test] fn test_only_new_changelog() { use breezyshim::tree::MutableTree; let td = tempfile::tempdir().unwrap(); let tree = create_standalone_workingtree(td.path(), "git").unwrap(); let lock_write = tree.lock_write(); std::fs::create_dir_all(td.path().join("debian")).unwrap(); std::fs::write( td.path().join("debian/changelog"), r###"blah (0.1) unstable; urgency=medium * Initial release. (Closes: #911016) -- Blah Sat, 13 Oct 2018 11:21:39 +0100 "###, ) .unwrap(); let basis_tree = tree.basis_tree().unwrap(); let lock_read = tree.lock_read(); let basis_lock_read = basis_tree.lock_read(); tree.add(&[Path::new("debian"), Path::new("debian/changelog")]) .unwrap(); let changes = tree .iter_changes(&basis_tree, None, None, None) .unwrap() .collect::, _>>() .unwrap(); assert!(only_changes_last_changelog_block( &tree, &tree.basis_tree().unwrap(), Path::new("debian/changelog"), changes.iter() ) .unwrap()); std::mem::drop(basis_lock_read); std::mem::drop(lock_read); std::mem::drop(lock_write); } #[test] fn test_changes_to_last_only_but_released() { let td = tempfile::tempdir().unwrap(); let tree = make_package_tree(td.path()); std::fs::write( td.path().join("debian/changelog"), r###"blah (0.2) unstable; urgency=medium * And a change. -- Blah Sat, 13 Oct 2018 11:21:39 +0100 blah (0.1) unstable; urgency=medium * Initial release. (Closes: #911016) -- Blah Sat, 13 Oct 2018 11:21:39 +0100 "###, ) .unwrap(); tree.build_commit() .message("release") .committer(COMMITTER) .commit() .unwrap(); std::fs::write( td.path().join("debian/changelog"), r###"blah (0.2) unstable; urgency=medium * And a change. * Team Upload. -- Blah Sat, 13 Oct 2018 11:21:39 +0100 blah (0.1) unstable; urgency=medium * Initial release. (Closes: #911016) -- Blah Sat, 13 Oct 2018 11:21:39 +0100 "###, ) .unwrap(); let basis_tree = tree.basis_tree().unwrap(); let lock_read = tree.lock_read(); let basis_lock_read = basis_tree.lock_read(); let changes = tree .iter_changes(&basis_tree, None, None, None) .unwrap() .collect::, _>>() .unwrap(); assert!(!only_changes_last_changelog_block( &tree, &tree.basis_tree().unwrap(), Path::new("debian/changelog"), changes.iter() ) .unwrap()); std::mem::drop(basis_lock_read); std::mem::drop(lock_read); } } } debian-analyzer-0.158.27/src/config.rs000064400000000000000000000131331046102023000155400ustar 00000000000000//! Lintian-brush configuration file. use crate::Certainty; use breezyshim::tree::WorkingTree; use configparser::ini::Ini; use log::warn; const SUPPORTED_KEYS: &[&str] = &[ "compat-release", "minimum-certainty", "allow-reformatting", "update-changelog", ]; /// Configuration file name pub const PACKAGE_CONFIG_FILENAME: &str = "debian/lintian-brush.conf"; /// Configuration file pub struct Config { obj: Ini, } impl Config { /// Load configuration from a working tree pub fn from_workingtree( tree: &WorkingTree, subpath: &std::path::Path, ) -> std::io::Result { let path = tree .abspath(&subpath.join(PACKAGE_CONFIG_FILENAME)) .unwrap(); Self::load_from_path(&path) } /// Load configuration from a path pub fn load_from_path(path: &std::path::Path) -> Result { let mut ini = Ini::new(); let data = std::fs::read_to_string(path)?; ini.read(data) .map_err(|e| std::io::Error::new(std::io::ErrorKind::Other, e))?; for (section, contents) in ini.get_map_ref() { if section != "default" { warn!( "unknown section {} in {}, ignoring.", section, path.display() ); continue; } for key in contents.keys() { if !SUPPORTED_KEYS.contains(&key.as_str()) { warn!( "unknown key {} in section {} in {}, ignoring.", key, section, path.display() ); continue; } } } Ok(Config { obj: ini }) } /// Return the compatibility release. pub fn compat_release(&self) -> Option { if let Some(value) = self.obj.get("default", "compat-release") { let codename = crate::release_info::resolve_release_codename(value.as_str(), None); if codename.is_none() { warn!("unknown compat release {}, ignoring.", value); } codename } else { None } } /// Return whether reformatting is allowed. pub fn allow_reformatting(&self) -> Option { match self.obj.getbool("default", "allow-reformatting") { Ok(value) => value, Err(e) => { warn!("invalid allow-reformatting value {}, ignoring.", e); None } } } /// Return the minimum certainty level for changes to be applied. pub fn minimum_certainty(&self) -> Option { self.obj .get("default", "minimum-certainty") .and_then(|value| { value .parse::() .map_err(|e| { warn!("invalid minimum-certainty value {}, ignoring.", value); e }) .ok() }) } /// Return whether the changelog should be updated. pub fn update_changelog(&self) -> Option { match self.obj.getbool("default", "update-changelog") { Ok(value) => value, Err(e) => { warn!("invalid update-changelog value {}, ignoring.", e); None } } } } #[cfg(test)] mod tests { use super::*; #[test] fn test_compat_release() { let td = tempfile::tempdir().unwrap(); std::fs::create_dir(td.path().join("debian")).unwrap(); std::fs::write( td.path().join("debian/lintian-brush.conf"), "compat-release = testing\n", ) .unwrap(); let cfg = Config::load_from_path(&td.path().join("debian/lintian-brush.conf")).unwrap(); let testing = crate::release_info::resolve_release_codename("testing", None); assert_eq!(cfg.compat_release(), testing); } #[test] fn test_minimum_certainty() { let td = tempfile::tempdir().unwrap(); std::fs::create_dir(td.path().join("debian")).unwrap(); std::fs::write( td.path().join("debian/lintian-brush.conf"), "minimum-certainty = possible\n", ) .unwrap(); let cfg = Config::load_from_path(&td.path().join("debian/lintian-brush.conf")).unwrap(); assert_eq!(cfg.minimum_certainty(), Some(Certainty::Possible)); } #[test] fn test_update_changelog() { let td = tempfile::tempdir().unwrap(); std::fs::create_dir(td.path().join("debian")).unwrap(); std::fs::write( td.path().join("debian/lintian-brush.conf"), "update-changelog = True\n", ) .unwrap(); let cfg = Config::load_from_path(&td.path().join("debian/lintian-brush.conf")).unwrap(); assert_eq!(cfg.update_changelog(), Some(true)); } #[test] fn test_unknown() { let td = tempfile::tempdir().unwrap(); std::fs::create_dir(td.path().join("debian")).unwrap(); std::fs::write( td.path().join("debian/lintian-brush.conf"), "unknown = dunno\n", ) .unwrap(); let cfg = Config::load_from_path(&td.path().join("debian/lintian-brush.conf")).unwrap(); assert_eq!(cfg.compat_release(), None); } #[test] fn test_missing() { let td = tempfile::tempdir().unwrap(); let path = td.path().join("debian/lintian-brush.conf"); let cfg = Config::load_from_path(&path); assert!(cfg.is_err()); } } debian-analyzer-0.158.27/src/control.rs000064400000000000000000001753631046102023000157710ustar 00000000000000//! Tools for working with Debian control files. use crate::editor::{Editor, EditorError, FsEditor, GeneratedFile}; use crate::relations::{ensure_relation, is_relation_implied}; use deb822_lossless::Paragraph; use debian_control::lossless::relations::Relations; use std::ops::{Deref, DerefMut}; use std::path::{Path, PathBuf}; /// Format a description based on summary and long description lines. pub fn format_description(summary: &str, long_description: Vec<&str>) -> String { let mut ret = summary.to_string() + "\n"; for line in long_description { ret.push(' '); ret.push_str(line); ret.push('\n'); } ret } #[derive(Debug, Clone, PartialEq, Eq, Copy)] /// The type of a control file template. pub enum TemplateType { /// A rule in the debian/rules file that generates the control file. Rules, /// Generated by gnome-pkg-tools. Gnome, /// Generated by pg_buildext. Postgresql, /// Generated by a set of files in the debian/control.in directory. Directory, /// Generated by cdbs. Cdbs, /// Generated by debcargo. Debcargo, } #[derive(Debug)] enum TemplateExpansionError { Failed(String), ExpandCommandMissing(String), UnknownTemplating(PathBuf, Option), Conflict(ChangeConflict), } impl From for TemplateExpansionError { fn from(e: ChangeConflict) -> Self { TemplateExpansionError::Conflict(e) } } impl std::fmt::Display for TemplateExpansionError { fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { match self { TemplateExpansionError::Failed(s) => write!(f, "Failed: {}", s), TemplateExpansionError::ExpandCommandMissing(s) => { write!(f, "Command not found: {}", s) } TemplateExpansionError::UnknownTemplating(p1, p2) => { if let Some(p2) = p2 { write!( f, "Unknown templating: {} -> {}", p1.display(), p2.display() ) } else { write!(f, "Unknown templating: {}", p1.display()) } } TemplateExpansionError::Conflict(c) => write!(f, "Conflict: {}", c), } } } impl std::error::Error for TemplateExpansionError {} /// Run the dh_gnome_clean command. /// /// This needs to do some post-hoc cleaning, since dh_gnome_clean writes various debhelper log /// files that should not be checked in. /// /// # Arguments /// * `path` - Path to run dh_gnome_clean in fn dh_gnome_clean(path: &std::path::Path) -> Result<(), TemplateExpansionError> { for entry in std::fs::read_dir(path.join("debian")).unwrap().flatten() { if entry .file_name() .to_string_lossy() .ends_with(".debhelper.log") { return Err(TemplateExpansionError::Failed( "pre-existing .debhelper.log files".to_string(), )); } } if !path.join("debian/changelog").exists() { return Err(TemplateExpansionError::Failed( "no changelog file".to_string(), )); } let result = std::process::Command::new("dh_gnome_clean") .current_dir(path) .output(); match result { Ok(output) => { if !output.status.success() { let stderr = String::from_utf8_lossy(&output.stderr); return Err(TemplateExpansionError::Failed(stderr.to_string())); } } Err(e) if e.kind() == std::io::ErrorKind::NotFound => { return Err(TemplateExpansionError::ExpandCommandMissing( "dh_gnome_clean".to_string(), )); } Err(e) => { return Err(TemplateExpansionError::Failed(e.to_string())); } } for entry in std::fs::read_dir(path.join("debian")).unwrap().flatten() { if entry .file_name() .to_string_lossy() .ends_with(".debhelper.log") { std::fs::remove_file(entry.path()).unwrap(); } } Ok(()) } /// Run the 'pg_buildext updatecontrol' command. /// /// # Arguments /// * `path` - Path to run pg_buildext updatecontrol in fn pg_buildext_updatecontrol(path: &std::path::Path) -> Result<(), TemplateExpansionError> { let result = std::process::Command::new("pg_buildext") .arg("updatecontrol") .current_dir(path) .output(); match result { Ok(output) => { if !output.status.success() { let stderr = String::from_utf8_lossy(&output.stderr); return Err(TemplateExpansionError::Failed(stderr.to_string())); } } Err(e) if e.kind() == std::io::ErrorKind::NotFound => { return Err(TemplateExpansionError::ExpandCommandMissing( "pg_buildext".to_string(), )); } Err(e) => { return Err(TemplateExpansionError::Failed(e.to_string())); } } Ok(()) } /// Expand a control template. /// /// # Arguments /// * `template_path` - Path to the control template /// * `path` - Path to the control file /// * `template_type` - Type of the template /// /// # Returns /// Ok if the template was successfully expanded fn expand_control_template( template_path: &std::path::Path, path: &std::path::Path, template_type: TemplateType, ) -> Result<(), TemplateExpansionError> { let package_root = path.parent().unwrap().parent().unwrap(); match template_type { TemplateType::Rules => { let path_time = match std::fs::metadata(path) { Ok(metadata) => Some(metadata.modified().unwrap()), Err(e) if e.kind() == std::io::ErrorKind::NotFound => None, Err(e) => panic!("Failed to get mtime of {}: {}", path.display(), e), }; while let Ok(metadata) = std::fs::metadata(template_path) { if Some(metadata.modified().unwrap()) == path_time { // Wait until mtime has changed, so that make knows to regenerate. filetime::set_file_mtime(template_path, filetime::FileTime::now()).unwrap(); } else { break; } } let result = std::process::Command::new("./debian/rules") .arg("debian/control") .current_dir(package_root) .output(); match result { Ok(output) => { if !output.status.success() { let stderr = String::from_utf8_lossy(&output.stderr); Err(TemplateExpansionError::Failed(format!( "Exit code {} running ./debian/rules debian/control: {}", output.status, stderr ))) } else { Ok(()) } } Err(e) => Err(TemplateExpansionError::Failed(format!( "Failed to run ./debian/rules debian/control: {}", e ))), } } TemplateType::Gnome => dh_gnome_clean(package_root), TemplateType::Postgresql => pg_buildext_updatecontrol(package_root), TemplateType::Cdbs => unreachable!(), TemplateType::Debcargo => unreachable!(), TemplateType::Directory => Err(TemplateExpansionError::UnknownTemplating( path.to_path_buf(), Some(template_path.to_path_buf()), )), } } #[derive(Debug, Clone)] struct Deb822Changes( std::collections::HashMap<(String, String), Vec<(String, Option, Option)>>, ); impl Deb822Changes { fn new() -> Self { Self(std::collections::HashMap::new()) } fn insert( &mut self, para_key: (String, String), field: String, old_value: Option, new_value: Option, ) { self.0 .entry(para_key) .or_default() .push((field, old_value, new_value)); } #[allow(dead_code)] fn normalized(&self) -> Vec<((&str, &str), Vec<(&str, Option<&str>, Option<&str>)>)> { let mut ret: Vec<_> = self .0 .iter() .map(|(k, v)| { ((k.0.as_str(), k.1.as_str()), { let mut v: Vec<_> = v .iter() .map(|(f, o, n)| (f.as_str(), o.as_deref(), n.as_deref())) .collect(); v.sort(); v }) }) .collect(); ret.sort_by_key(|(k, _)| *k); ret } } // Update a control file template based on changes to the file itself. // // # Arguments // * `template_path` - Path to the control template // * `path` - Path to the control file // * `changes` - Changes to apply // * `expand_template` - Whether to expand the template after updating it // // # Returns // Ok if the template was successfully updated fn update_control_template( template_path: &std::path::Path, template_type: TemplateType, path: &std::path::Path, changes: Deb822Changes, expand_template: bool, ) -> Result { if template_type == TemplateType::Directory { // We can't handle these yet return Err(TemplateExpansionError::UnknownTemplating( path.to_path_buf(), Some(template_path.to_path_buf()), )); } let mut template_editor = FsEditor::::new(template_path, true, false).unwrap(); let resolve_conflict = match template_type { TemplateType::Cdbs => Some(resolve_cdbs_template as ResolveDeb822Conflict), _ => None, }; apply_changes(&mut template_editor, changes.clone(), resolve_conflict)?; if !template_editor.has_changed() { // A bit odd, since there were changes to the output file. Anyway. return Ok(false); } match template_editor.commit() { Ok(_) => {} Err(e) => return Err(TemplateExpansionError::Failed(e.to_string())), } if expand_template { match template_type { TemplateType::Cdbs => { let mut editor = FsEditor::::new(path, true, false).unwrap(); apply_changes(&mut editor, changes, None)?; match editor.commit() { Ok(_) => {} Err(e) => return Err(TemplateExpansionError::Failed(e.to_string())), } } _ => { expand_control_template(template_path, path, template_type)?; } } } Ok(true) } #[derive(Debug, PartialEq, Eq)] /// A change conflict. pub struct ChangeConflict { /// Paragraph key, i.e. ("Source", "foo") pub para_key: (String, String), /// Field that conflicted pub field: String, /// Old value in the control file pub actual_old_value: Option, /// Old value in the template pub template_old_value: Option, /// New value in the control file pub actual_new_value: Option, } impl std::fmt::Display for ChangeConflict { fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { write!( f, "{}/{}: {} -> {} (template: {})", self.para_key.0, self.para_key.1, self.actual_old_value.as_deref().unwrap_or(""), self.actual_new_value.as_deref().unwrap_or(""), self.template_old_value.as_deref().unwrap_or("") ) } } impl std::error::Error for ChangeConflict {} type ResolveDeb822Conflict = fn( para_key: (&str, &str), field: &str, actual_old_value: Option<&str>, template_old_value: Option<&str>, actual_new_value: Option<&str>, ) -> Result, ChangeConflict>; fn resolve_cdbs_template( para_key: (&str, &str), field: &str, actual_old_value: Option<&str>, template_old_value: Option<&str>, actual_new_value: Option<&str>, ) -> Result, ChangeConflict> { if para_key.0 == "Source" && field == "Build-Depends" && template_old_value.is_some() && actual_old_value.is_some() && actual_new_value.is_some() { if actual_new_value .unwrap() .contains(actual_old_value.unwrap()) { // We're simply adding to the existing list return Ok(Some( actual_new_value .unwrap() .replace(actual_old_value.unwrap(), template_old_value.unwrap()), )); } else { let old_rels: Relations = actual_old_value.unwrap().parse().unwrap(); let new_rels: Relations = actual_new_value.unwrap().parse().unwrap(); let template_old_value = template_old_value.unwrap(); let (mut ret, errors) = Relations::parse_relaxed(template_old_value, true); if !errors.is_empty() { log::debug!("Errors parsing template value: {:?}", errors); } for v in new_rels.entries() { if old_rels.entries().any(|r| is_relation_implied(&v, &r)) { continue; } ensure_relation(&mut ret, v); } return Ok(Some(ret.to_string())); } } Err(ChangeConflict { para_key: (para_key.0.to_string(), para_key.1.to_string()), field: field.to_string(), actual_old_value: actual_old_value.map(|v| v.to_string()), template_old_value: template_old_value.map(|v| v.to_string()), actual_new_value: actual_new_value.map(|s| s.to_string()), }) } /// Guess the type for a control template. /// /// # Arguments /// * `template_path` - Path to the control template /// * `debian_path` - Path to the debian directory /// /// # Returns /// Template type; None if unknown pub fn guess_template_type( template_path: &std::path::Path, debian_path: Option<&std::path::Path>, ) -> Option { // TODO(jelmer): This should use a proper make file parser of some sort.. if let Some(debian_path) = debian_path { match std::fs::read(debian_path.join("rules")) { Ok(file) => { for line in file.split(|&c| c == b'\n') { if line.starts_with(b"debian/control:") { return Some(TemplateType::Rules); } if line.starts_with(b"debian/%: debian/%.in") { return Some(TemplateType::Rules); } if line.starts_with(b"include /usr/share/blends-dev/rules") { return Some(TemplateType::Rules); } } } Err(e) if e.kind() == std::io::ErrorKind::NotFound => {} Err(e) => panic!( "Failed to read {}: {}", debian_path.join("rules").display(), e ), } } match std::fs::read(template_path) { Ok(template) => { let template_str = std::str::from_utf8(&template).unwrap(); if template_str.contains("@GNOME_TEAM@") { return Some(TemplateType::Gnome); } if template_str.contains("PGVERSION") { return Some(TemplateType::Postgresql); } if template_str.contains("@cdbs@") { return Some(TemplateType::Cdbs); } let control = debian_control::Control::read_relaxed(std::io::Cursor::new(&template)) .unwrap() .0; let build_depends = control.source().and_then(|s| s.build_depends()); if build_depends.iter().any(|d| { d.entries() .any(|e| e.relations().any(|r| r.name() == "gnome-pkg-tools")) }) { return Some(TemplateType::Gnome); } if build_depends.iter().any(|d| { d.entries() .any(|e| e.relations().any(|r| r.name() == "cdbs")) }) { return Some(TemplateType::Cdbs); } } Err(_) if template_path.is_dir() => { return Some(TemplateType::Directory); } Err(e) => panic!("Failed to read {}: {}", template_path.display(), e), } if let Some(debian_path) = debian_path { if debian_path.join("debcargo.toml").exists() { return Some(TemplateType::Debcargo); } } None } /// Apply a set of changes to this deb822 instance. /// /// # Arguments /// * `changes` - Changes to apply /// * `resolve_conflict` - Callback to resolve conflicts fn apply_changes( deb822: &mut deb822_lossless::Deb822, mut changes: Deb822Changes, resolve_conflict: Option, ) -> Result<(), ChangeConflict> { fn default_resolve_conflict( para_key: (&str, &str), field: &str, actual_old_value: Option<&str>, template_old_value: Option<&str>, actual_new_value: Option<&str>, ) -> Result, ChangeConflict> { Err(ChangeConflict { para_key: (para_key.0.to_string(), para_key.1.to_string()), field: field.to_string(), actual_old_value: actual_old_value.map(|v| v.to_string()), template_old_value: template_old_value.map(|v| v.to_string()), actual_new_value: actual_new_value.map(|s| s.to_string()), }) } let resolve_conflict = resolve_conflict.unwrap_or(default_resolve_conflict); for mut paragraph in deb822.paragraphs() { for item in paragraph.items().collect::>() { for (key, old_value, mut new_value) in changes.0.remove(&item).unwrap_or_default() { if paragraph.get(&key) != old_value { new_value = resolve_conflict( (&item.0, &item.1), &key, old_value.as_deref(), paragraph.get(&key).as_deref(), new_value.as_deref(), )?; } if let Some(new_value) = new_value.as_ref() { paragraph.set(&key, new_value); } else { paragraph.remove(&key); } } } } // Add any new paragraphs that weren't processed earlier for (key, p) in changes.0.drain() { let mut paragraph = deb822.add_paragraph(); for (field, old_value, mut new_value) in p { if old_value.is_some() { new_value = resolve_conflict( (&key.0, &key.1), &field, old_value.as_deref(), paragraph.get(&field).as_deref(), new_value.as_deref(), )?; } if let Some(new_value) = new_value { paragraph.set(&field, &new_value); } } } Ok(()) } fn find_template_path(path: &Path) -> Option { for ext in &["in", "m4"] { let template_path = path.with_extension(ext); if template_path.exists() { return Some(template_path); } } None } /// An editor for a control file that may be generated from a template. /// /// This editor will automatically expand the template if it does not exist. /// It will also automatically update the template if the control file is changed. /// /// # Example /// /// ```rust /// use std::path::Path; /// use debian_analyzer::control::TemplatedControlEditor; /// let td = tempfile::tempdir().unwrap(); /// let mut editor = TemplatedControlEditor::create(td.path().join("control")).unwrap(); /// editor.add_source("foo").set_architecture(Some("all")); /// editor.commit().unwrap(); /// ``` pub struct TemplatedControlEditor { /// The primary editor for the control file. primary: FsEditor, /// The template that was used to generate the control file. template: Option