diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 9a8932f..3862952 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -64,7 +64,7 @@ jobs: - s390x-unknown-linux-gnu - aarch64-apple-darwin - x86_64-apple-darwin - - x86_64-pc-windows-gnu + # - x86_64-pc-windows-gnu runs-on: ${{ (matrix.target == 'aarch64-apple-darwin' || matrix.target == 'x86_64-apple-darwin') && 'macos-latest' || 'ubuntu-latest' }} steps: - name: Checkout repository diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 7d877e8..d2e40a8 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -10,7 +10,7 @@ on: jobs: test: - runs-on: ubuntu-latest + runs-on: macos-latest steps: - name: Checkout repository uses: actions/checkout@v2 diff --git a/Cargo.lock b/Cargo.lock index 0615437..814e943 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4,9 +4,9 @@ version = 3 [[package]] name = "addr2line" -version = "0.20.0" +version = "0.21.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f4fa78e18c64fce05e902adecd7a5eed15a5e0a3439f7b0e169f0252214865e3" +checksum = "8a30b2e23b9e17a9f90641c7ab1549cd9b44f296d3ccbf309d2863cfe398a0cb" dependencies = [ "gimli", ] @@ -19,9 +19,9 @@ checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" [[package]] name = "aho-corasick" -version = "1.0.2" +version = "1.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "43f6cb1bf222025340178f382c426f13757b2960e89779dfcb319c32542a5a41" +checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916" dependencies = [ "memchr", ] @@ -43,58 +43,58 @@ dependencies = [ [[package]] name = "anstream" -version = "0.3.2" +version = "0.6.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ca84f3628370c59db74ee214b3263d58f9aadd9b4fe7e711fd87dc452b7f163" +checksum = "418c75fa768af9c03be99d17643f93f79bbba589895012a80e3452a19ddda15b" dependencies = [ "anstyle", "anstyle-parse", "anstyle-query", "anstyle-wincon", "colorchoice", - "is-terminal", + "is_terminal_polyfill", "utf8parse", ] [[package]] name = "anstyle" -version = "1.0.1" +version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3a30da5c5f2d5e72842e00bcb57657162cdabef0931f40e2deb9b4140440cecd" +checksum = "038dfcf04a5feb68e9c60b21c9625a54c2c0616e79b72b0fd87075a056ae1d1b" [[package]] name = "anstyle-parse" -version = "0.2.1" +version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "938874ff5980b03a87c5524b3ae5b59cf99b1d6bc836848df7bc5ada9643c333" +checksum = "c03a11a9034d92058ceb6ee011ce58af4a9bf61491aa7e1e59ecd24bd40d22d4" dependencies = [ "utf8parse", ] [[package]] name = "anstyle-query" -version = "1.0.0" +version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ca11d4be1bab0c8bc8734a9aa7bf4ee8316d462a08c6ac5052f888fef5b494b" +checksum = "a64c907d4e79225ac72e2a354c9ce84d50ebb4586dee56c82b3ee73004f537f5" dependencies = [ - "windows-sys 0.48.0", + "windows-sys 0.52.0", ] [[package]] name = "anstyle-wincon" -version = "1.0.1" +version = "3.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "180abfa45703aebe0093f79badacc01b8fd4ea2e35118747e5811127f926e188" +checksum = "61a38449feb7068f52bb06c12759005cf459ee52bb4adc1d5a7c4322d716fb19" dependencies = [ "anstyle", - "windows-sys 0.48.0", + "windows-sys 0.52.0", ] [[package]] name = "assert_cmd" -version = "2.0.12" +version = "2.0.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "88903cb14723e4d4003335bb7f8a14f27691649105346a0f0957466c096adfe6" +checksum = "ed72493ac66d5804837f480ab3766c72bdfab91a65e565fc54fa9e42db0073a8" dependencies = [ "anstyle", "bstr", @@ -107,15 +107,15 @@ dependencies = [ [[package]] name = "autocfg" -version = "1.1.0" +version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" +checksum = "0c4b4d0bd25bd0b74681c0ad21497610ce1b7c91b1022cd21c80c6fbdd9476b0" [[package]] name = "backtrace" -version = "0.3.68" +version = "0.3.71" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4319208da049c43661739c5fade2ba182f09d1dc2299b32298d3a31692b17e12" +checksum = "26b05800d2e817c8b3b4b54abd461726265fa9789ae34330622f2db9ee696f9d" dependencies = [ "addr2line", "cc", @@ -128,63 +128,54 @@ dependencies = [ [[package]] name = "base64" -version = "0.13.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8" - -[[package]] -name = "base64" -version = "0.21.2" +version = "0.22.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "604178f6c5c21f02dc555784810edfb88d34ac2c73b2eae109655649ee73ce3d" +checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" [[package]] name = "bindgen" -version = "0.64.0" +version = "0.69.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c4243e6031260db77ede97ad86c27e501d646a27ab57b59a574f725d98ab1fb4" +checksum = "a00dc851838a2120612785d195287475a3ac45514741da670b735818822129a0" dependencies = [ - "bitflags 1.3.2", + "bitflags", "cexpr", "clang-sys", + "itertools", "lazy_static", "lazycell", - "peeking_take_while", "proc-macro2", "quote", "regex", "rustc-hash", "shlex", - "syn 1.0.109", + "syn", ] [[package]] name = "bitflags" -version = "1.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" - -[[package]] -name = "bitflags" -version = "2.3.3" +version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "630be753d4e58660abd17930c71b647fe46c27ea6b63cc59e1e3851406972e42" +checksum = "cf4b9d6a944f767f8e5e0db018570623c85f3d925ac718db4e06d0187adb21c1" [[package]] name = "bollard" -version = "0.14.0" +version = "0.16.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af254ed2da4936ef73309e9597180558821cb16ae9bba4cb24ce6b612d8d80ed" +checksum = "0aed08d3adb6ebe0eff737115056652670ae290f177759aac19c30456135f94c" dependencies = [ - "base64 0.21.2", + "base64", "bollard-stubs", "bytes", "futures-core", "futures-util", "hex", "http", + "http-body-util", "hyper", - "hyperlocal", + "hyper-named-pipe", + "hyper-util", + "hyperlocal-next", "log", "pin-project-lite", "serde", @@ -195,25 +186,27 @@ dependencies = [ "thiserror", "tokio", "tokio-util", + "tower-service", "url", "winapi", ] [[package]] name = "bollard-stubs" -version = "1.42.0-rc.7" +version = "1.44.0-rc.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "602bda35f33aeb571cef387dcd4042c643a8bf689d8aaac2cc47ea24cb7bc7e0" +checksum = "709d9aa1c37abb89d40f19f5d0ad6f0d88cb1581264e571c9350fc5bb89cf1c5" dependencies = [ "serde", + "serde_repr", "serde_with", ] [[package]] name = "bstr" -version = "1.6.0" +version = "1.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6798148dccfbff0fae41c7574d2fa8f1ef3492fba0face179de5d8d447d67b05" +checksum = "05efc5cfd9110c8416e471df0e96702d58690178e206e61b7173706673c93706" dependencies = [ "memchr", "regex-automata", @@ -222,27 +215,21 @@ dependencies = [ [[package]] name = "bumpalo" -version = "3.13.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a3e2c3daef883ecc1b5d58c15adae93470a91d425f3532ba1695849656af3fc1" - -[[package]] -name = "byteorder" -version = "1.4.3" +version = "3.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610" +checksum = "79296716171880943b8470b5f8d03aa55eb2e645a4874bdbb28adb49162e012c" [[package]] name = "bytes" -version = "1.4.0" +version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89b2fd2a0dcf38d7971e2194b6b6eebab45ae01067456a7fd93d5547a61b70be" +checksum = "514de17de45fdb8dc022b1a7975556c53c86f9f0aa5f534b98977b171857c2c9" [[package]] name = "cc" -version = "1.0.79" +version = "1.0.97" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "50d30906286121d95be3d479533b458f87493b30a4b5f79a607db8f5d11aa91f" +checksum = "099a5357d84c4c61eb35fc8eafa9a79a902c2f76911e5747ced4e032edd8d9b4" [[package]] name = "cexpr" @@ -259,24 +246,30 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" +[[package]] +name = "cfg_aliases" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fd16c4719339c4530435d38e511904438d07cce7950afa3718a84ac36c10e89e" + [[package]] name = "chrono" -version = "0.4.26" +version = "0.4.38" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec837a71355b28f6556dbd569b37b3f363091c0bd4b2e735674521b4c5fd9bc5" +checksum = "a21f936df1771bf62b77f047b726c4625ff2e8aa607c01ec06e5a05bd8463401" dependencies = [ "android-tzdata", "iana-time-zone", "num-traits", "serde", - "winapi", + "windows-targets 0.52.5", ] [[package]] name = "clang-sys" -version = "1.6.1" +version = "1.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c688fc74432808e3eb684cae8830a86be1d66a2bd58e1f248ed0960a590baf6f" +checksum = "67523a3b4be3ce1989d607a828d036249522dd9c1c8de7f4dd2dae43a37369d1" dependencies = [ "glob", "libc", @@ -285,20 +278,19 @@ dependencies = [ [[package]] name = "clap" -version = "4.3.19" +version = "4.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5fd304a20bff958a57f04c4e96a2e7594cc4490a0e809cbd48bb6437edaa452d" +checksum = "90bc066a67923782aa8515dbaea16946c5bcc5addbd668bb80af688e53e548a0" dependencies = [ "clap_builder", "clap_derive", - "once_cell", ] [[package]] name = "clap-verbosity-flag" -version = "2.0.1" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1eef05769009513df2eb1c3b4613e7fad873a14c600ff025b08f250f59fee7de" +checksum = "bb9b20c0dd58e4c2e991c8d203bbeb76c11304d1011659686b5b644bc29aa478" dependencies = [ "clap", "log", @@ -306,9 +298,9 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.3.19" +version = "4.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "01c6a3f08f1fe5662a35cfe393aec09c4df95f60ee93b7556505260f75eee9e1" +checksum = "ae129e2e766ae0ec03484e609954119f123cc1fe650337e155d03b022f24f7b4" dependencies = [ "anstream", "anstyle", @@ -318,43 +310,53 @@ dependencies = [ [[package]] name = "clap_derive" -version = "4.3.12" +version = "4.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "54a9bb5758fc5dfe728d1019941681eccaf0cf8a4189b692a0ee2f2ecf90a050" +checksum = "528131438037fd55894f62d6e9f068b8f45ac57ffa77517819645d10aed04f64" dependencies = [ "heck", "proc-macro2", "quote", - "syn 2.0.27", + "syn", ] [[package]] name = "clap_lex" -version = "0.5.0" +version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2da6da31387c7e4ef160ffab6d5e7f00c42626fe39aea70a7b0f1773f7dd6c1b" +checksum = "98cc8fbded0c607b7ba9dd60cd98df59af97e84d24e49c8557331cfc26d301ce" [[package]] name = "colorchoice" -version = "1.0.0" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "acbf1af155f9b9ef647e42cdc158db4b64a1b61f743629225fde6f3e0be2a7c7" +checksum = "0b6a852b24ab71dffc585bcb46eaf7959d175cb865a7152e35b348d1b2960422" [[package]] name = "core-foundation-sys" -version = "0.8.4" +version = "0.8.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e496a50fda8aacccc86d7529e2c1e0892dbd0f898a6b5645b5561b89c3210efa" +checksum = "06ea2b9bc92be3c2baa9334a323ebca2d6f074ff852cd1d7b11064035cd3868f" [[package]] name = "crc32fast" -version = "1.3.2" +version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b540bd8bc810d3885c6ea91e2018302f68baba2129ab3e88f32389ee9370880d" +checksum = "b3855a8a784b474f333699ef2bbca9db2c4a1f6d9088a90a2d25b1eb53111eaa" dependencies = [ "cfg-if", ] +[[package]] +name = "deranged" +version = "0.3.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b42b6fa04a440b495c8b04d0e71b707c585f83cb9cb28cf8cd0d976c315e31b4" +dependencies = [ + "powerfmt", + "serde", +] + [[package]] name = "difflib" version = "0.4.0" @@ -367,74 +369,68 @@ version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fea41bba32d969b513997752735605054bc0dfa92b4c56bf1189f2e174be7a10" +[[package]] +name = "downcast" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1435fa1053d8b2fbbe9be7e97eca7f33d37b28409959813daefc1446a14247f1" + [[package]] name = "either" -version = "1.9.0" +version = "1.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a26ae43d7bcc3b814de94796a5e736d4029efb0ee900c12e2d54c993ad1a1e07" +checksum = "a47c1c47d2f5964e29c61246e81db715514cd532db6b5116a25ea3c03d6780a2" [[package]] -name = "env_logger" -version = "0.10.0" +name = "env_filter" +version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85cdab6a89accf66733ad5a1693a4dcced6aeff64602b634530dd73c1f3ee9f0" +checksum = "a009aa4810eb158359dda09d0c87378e4bbb89b5a801f016885a4707ba24f7ea" dependencies = [ - "humantime", - "is-terminal", "log", "regex", - "termcolor", ] [[package]] -name = "equivalent" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" - -[[package]] -name = "errno" -version = "0.2.8" +name = "env_logger" +version = "0.11.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f639046355ee4f37944e44f60642c6f3a7efa3cf6b78c78a0d989a8ce6c396a1" +checksum = "38b35839ba51819680ba087cd351788c9a3c476841207e0b8cee0b04722343b9" dependencies = [ - "errno-dragonfly", - "libc", - "winapi", + "anstream", + "anstyle", + "env_filter", + "humantime", + "log", ] [[package]] -name = "errno" -version = "0.3.1" +name = "equivalent" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4bcfec3a70f97c962c307b2d2c56e358cf1d00b558d74262b5f929ee8cc7e73a" -dependencies = [ - "errno-dragonfly", - "libc", - "windows-sys 0.48.0", -] +checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" [[package]] -name = "errno-dragonfly" -version = "0.1.2" +name = "errno" +version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aa68f1b12764fab894d2755d2518754e71b4fd80ecfb822714a1206c2aab39bf" +checksum = "534c5cf6194dfab3db3242765c03bbe257cf92f22b38f6bc0c58d59108a820ba" dependencies = [ - "cc", "libc", + "windows-sys 0.52.0", ] [[package]] name = "fastrand" -version = "2.0.0" +version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6999dc1837253364c2ebb0704ba97994bd874e8f195d665c50b7548f6ea92764" +checksum = "9fc0510504f03c51ada170672ac806f1f105a88aa97a5281117e1ddc3368e51a" [[package]] name = "flate2" -version = "1.0.26" +version = "1.0.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b9429470923de8e8cbd4d2dc513535400b4b3fef0319fb5c4e1f520a7bef743" +checksum = "5f54427cfd1c7829e2a139fcefea601bf088ebca651d2bf53ebc600eac295dae" dependencies = [ "crc32fast", "miniz_oxide", @@ -448,56 +444,62 @@ checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" [[package]] name = "form_urlencoded" -version = "1.2.0" +version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a62bc1cf6f830c2ec14a513a9fb124d0a213a629668a4186f329db21fe045652" +checksum = "e13624c2627564efccf4934284bdd98cbaa14e79b0b5a141218e507b3a823456" dependencies = [ "percent-encoding", ] +[[package]] +name = "fragile" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c2141d6d6c8512188a7891b4b01590a45f6dac67afb4f255c4124dbb86d4eaa" + [[package]] name = "futures-channel" -version = "0.3.28" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "955518d47e09b25bbebc7a18df10b81f0c766eaf4c4f1cccef2fca5f2a4fb5f2" +checksum = "eac8f7d7865dcb88bd4373ab671c8cf4508703796caa2b1985a9ca867b3fcb78" dependencies = [ "futures-core", ] [[package]] name = "futures-core" -version = "0.3.28" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4bca583b7e26f571124fe5b7561d49cb2868d79116cfa0eefce955557c6fee8c" +checksum = "dfc6580bb841c5a68e9ef15c77ccc837b40a7504914d52e47b8b0e9bbda25a1d" [[package]] name = "futures-macro" -version = "0.3.28" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89ca545a94061b6365f2c7355b4b32bd20df3ff95f02da9329b34ccc3bd6ee72" +checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac" dependencies = [ "proc-macro2", "quote", - "syn 2.0.27", + "syn", ] [[package]] name = "futures-sink" -version = "0.3.28" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f43be4fe21a13b9781a69afa4985b0f6ee0e1afab2c6f454a8cf30e2b2237b6e" +checksum = "9fb8e00e87438d937621c1c6269e53f536c14d3fbd6a042bb24879e57d474fb5" [[package]] name = "futures-task" -version = "0.3.28" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "76d3d132be6c0e6aa1534069c705a74a5997a356c0dc2f86a47765e5617c5b65" +checksum = "38d84fa142264698cdce1a9f9172cf383a0c82de1bddcf3092901442c4097004" [[package]] name = "futures-util" -version = "0.3.28" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26b01e40b772d54cf6c6d721c1d1abd0647a0106a12ecaa1c186273392a69533" +checksum = "3d6401deb83407ab3da39eba7e33987a73c3df0c82b4bb5813ee871c19c41d48" dependencies = [ "futures-core", "futures-macro", @@ -509,9 +511,9 @@ dependencies = [ [[package]] name = "gimli" -version = "0.27.3" +version = "0.28.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6c80984affa11d98d1b88b66ac8853f143217b399d3c74116778ff8fdb4ed2e" +checksum = "4271d37baee1b8c7e4b708028c57d816cf9d2434acb33a549475f78c181f6253" [[package]] name = "glob" @@ -519,25 +521,6 @@ version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b" -[[package]] -name = "h2" -version = "0.3.26" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "81fe527a889e1532da5c525686d96d4c2e74cdd345badf8dfef9f6b39dd5f5e8" -dependencies = [ - "bytes", - "fnv", - "futures-core", - "futures-sink", - "futures-util", - "http", - "indexmap 2.2.6", - "slab", - "tokio", - "tokio-util", - "tracing", -] - [[package]] name = "hashbrown" version = "0.12.3" @@ -552,15 +535,15 @@ checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" [[package]] name = "heck" -version = "0.4.1" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" +checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" [[package]] name = "hermit-abi" -version = "0.3.2" +version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "443144c8cdadd93ebf52ddb4056d257f5b52c04d3c804e657d19eb73fc33668b" +checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024" [[package]] name = "hex" @@ -570,9 +553,9 @@ checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" [[package]] name = "http" -version = "0.2.9" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd6effc99afb63425aff9b05836f029929e345a6148a14b7ecd5ab67af944482" +checksum = "21b9ddb458710bc376481b842f5da65cdf31522de232c1ca8146abce2a358258" dependencies = [ "bytes", "fnv", @@ -581,12 +564,24 @@ dependencies = [ [[package]] name = "http-body" -version = "0.4.5" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d5f38f16d184e36f2408a55281cd658ecbd3ca05cce6d6510a176eca393e26d1" +checksum = "1cac85db508abc24a2e48553ba12a996e87244a0395ce011e62b37158745d643" dependencies = [ "bytes", "http", +] + +[[package]] +name = "http-body-util" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0475f8b2ac86659c21b64320d5d653f9efe42acd2a4e560073ec61a155a34f1d" +dependencies = [ + "bytes", + "futures-core", + "http", + "http-body", "pin-project-lite", ] @@ -596,12 +591,6 @@ version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d897f394bad6a705d5f4104762e116a75639e470d80901eed05a860a95cb1904" -[[package]] -name = "httpdate" -version = "1.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c4a1e36c821dbe04574f602848a19f742f4fb3c98d40449f11bcad18d6b17421" - [[package]] name = "humantime" version = "2.1.0" @@ -610,53 +599,85 @@ checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4" [[package]] name = "hyper" -version = "0.14.27" +version = "1.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ffb1cfd654a8219eaef89881fdb3bb3b1cdc5fa75ded05d6933b2b382e395468" +checksum = "fe575dd17d0862a9a33781c8c4696a55c320909004a67a00fb286ba8b1bc496d" dependencies = [ "bytes", "futures-channel", - "futures-core", "futures-util", - "h2", "http", "http-body", "httparse", - "httpdate", "itoa", "pin-project-lite", + "smallvec", + "tokio", + "want", +] + +[[package]] +name = "hyper-named-pipe" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "73b7d8abf35697b81a825e386fc151e0d503e8cb5fcb93cc8669c376dfd6f278" +dependencies = [ + "hex", + "hyper", + "hyper-util", + "pin-project-lite", + "tokio", + "tower-service", + "winapi", +] + +[[package]] +name = "hyper-util" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ca38ef113da30126bbff9cd1705f9273e15d45498615d138b0c20279ac7a76aa" +dependencies = [ + "bytes", + "futures-channel", + "futures-util", + "http", + "http-body", + "hyper", + "pin-project-lite", "socket2", "tokio", + "tower", "tower-service", "tracing", - "want", ] [[package]] -name = "hyperlocal" -version = "0.8.0" +name = "hyperlocal-next" +version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fafdf7b2b2de7c9784f76e02c0935e65a8117ec3b768644379983ab333ac98c" +checksum = "acf569d43fa9848e510358c07b80f4adf34084ddc28c6a4a651ee8474c070dcc" dependencies = [ - "futures-util", "hex", + "http-body-util", "hyper", - "pin-project", + "hyper-util", + "pin-project-lite", "tokio", + "tower-service", ] [[package]] name = "iana-time-zone" -version = "0.1.57" +version = "0.1.60" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2fad5b825842d2b38bd206f3e81d6957625fd7f0a361e345c30e01a0ae2dd613" +checksum = "e7ffbb5a1b541ea2561f8c41c087286cc091e21e556a4f09a8f6cbf17b69b141" dependencies = [ "android_system_properties", "core-foundation-sys", "iana-time-zone-haiku", "js-sys", "wasm-bindgen", - "windows", + "windows-core", ] [[package]] @@ -670,9 +691,9 @@ dependencies = [ [[package]] name = "idna" -version = "0.4.0" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7d20d6b07bfbc108882d88ed8e37d39636dcc260e15e30c45e6ba089610b917c" +checksum = "634d9b1461af396cad843f47fdba5597a4f9e6ddd4bfb6ff5d85028c25cb12f6" dependencies = [ "unicode-bidi", "unicode-normalization", @@ -697,71 +718,56 @@ checksum = "168fb715dda47215e360912c096649d23d58bf392ac62f73919e831745e40f26" dependencies = [ "equivalent", "hashbrown 0.14.5", + "serde", ] [[package]] -name = "io-lifetimes" -version = "1.0.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eae7b9aee968036d54dce06cebaefd919e4472e753296daccd6d344e3e2df0c2" -dependencies = [ - "hermit-abi", - "libc", - "windows-sys 0.48.0", -] - -[[package]] -name = "is-terminal" -version = "0.4.9" +name = "is_terminal_polyfill" +version = "1.70.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cb0889898416213fab133e1d33a0e5858a48177452750691bde3666d0fdbaf8b" -dependencies = [ - "hermit-abi", - "rustix 0.38.4", - "windows-sys 0.48.0", -] +checksum = "f8478577c03552c21db0e2724ffb8986a5ce7af88107e6be5d2ee6e158c12800" [[package]] name = "itertools" -version = "0.10.5" +version = "0.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b0fd2260e829bddf4cb6ea802289de2f86d6a7a690192fbe91b3f46e0f2c8473" +checksum = "ba291022dbbd398a455acf126c1e341954079855bc60dfdda641363bd6922569" dependencies = [ "either", ] [[package]] name = "itoa" -version = "1.0.9" +version = "1.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af150ab688ff2122fcef229be89cb50dd66af9e01a4ff320cc137eecc9bacc38" +checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b" [[package]] name = "js-sys" -version = "0.3.64" +version = "0.3.69" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c5f195fe497f702db0f318b07fdd68edb16955aed830df8363d837542f8f935a" +checksum = "29c15563dc2726973df627357ce0c9ddddbea194836909d655df6a75d2cf296d" dependencies = [ "wasm-bindgen", ] [[package]] name = "killport" -version = "0.9.2" +version = "1.0.0" dependencies = [ "assert_cmd", "bollard", "clap", "clap-verbosity-flag", "env_logger", - "libc", "libproc", "log", + "mockall", "nix", "procfs", "tempfile", "tokio", - "windows-sys 0.48.0", + "windows-sys 0.52.0", ] [[package]] @@ -784,57 +790,42 @@ checksum = "ae743338b92ff9146ce83992f766a31066a91a8c84a45e0e9f21e7cf6de6d346" [[package]] name = "libloading" -version = "0.7.4" +version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b67380fd3b2fbe7527a606e18729d21c6f3951633d0500574c4dc22d2d638b9f" +checksum = "0c2a198fb6b0eada2a8df47933734e6d35d350665a33a3593d7164fa52c75c19" dependencies = [ "cfg-if", - "winapi", + "windows-targets 0.52.5", ] [[package]] name = "libproc" -version = "0.13.0" +version = "0.14.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b18cbf29f8ff3542ba22bdce9ac610fcb75d74bb4e2b306b2a2762242025b4f" +checksum = "ae9ea4b75e1a81675429dafe43441df1caea70081e82246a8cccf514884a88bb" dependencies = [ "bindgen", - "errno 0.2.8", + "errno", "libc", ] [[package]] name = "linux-raw-sys" -version = "0.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f051f77a7c8e6957c0696eac88f26b0117e54f52d3fc682ab19397a8812846a4" - -[[package]] -name = "linux-raw-sys" -version = "0.4.3" +version = "0.4.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09fc20d2ca12cb9f044c93e3bd6d32d523e6e2ec3db4f7b2939cd99026ecd3f0" +checksum = "01cda141df6706de531b6c46c3a33ecca755538219bd484262fa09410c13539c" [[package]] name = "log" -version = "0.4.19" +version = "0.4.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b06a4cde4c0f271a446782e3eff8de789548ce57dbc8eca9292c27f4a42004b4" +checksum = "90ed8c1e510134f979dbc4f070f87d4313098b704861a105fe34231c70a3901c" [[package]] name = "memchr" -version = "2.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d" - -[[package]] -name = "memoffset" -version = "0.7.1" +version = "2.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5de893c32cde5f383baa4c04c5d6dbdd735cfd4a794b0debdb2bb1b421da5ff4" -dependencies = [ - "autocfg", -] +checksum = "6c8640c5d730cb13ebd907d8d04b52f55ac9a2eec55b440c8892f40d56c76c1d" [[package]] name = "minimal-lexical" @@ -844,9 +835,9 @@ checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" [[package]] name = "miniz_oxide" -version = "0.7.1" +version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e7810e0be55b428ada41041c41f32c9f1a42817901b4ccf45fa3d4b6561e74c7" +checksum = "9d811f3e15f28568be3407c8e7fdb6514c1cda3cb30683f15b6a1a1dc4ea14a7" dependencies = [ "adler", ] @@ -862,18 +853,43 @@ dependencies = [ "windows-sys 0.48.0", ] +[[package]] +name = "mockall" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "43766c2b5203b10de348ffe19f7e54564b64f3d6018ff7648d1e2d6d3a0f0a48" +dependencies = [ + "cfg-if", + "downcast", + "fragile", + "lazy_static", + "mockall_derive", + "predicates", + "predicates-tree", +] + +[[package]] +name = "mockall_derive" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "af7cbce79ec385a1d4f54baa90a76401eb15d9cab93685f62e7e9f942aa00ae2" +dependencies = [ + "cfg-if", + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "nix" -version = "0.26.2" +version = "0.28.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bfdda3d196821d6af13126e40375cdf7da646a96114af134d5f417a9a1dc8e1a" +checksum = "ab2156c4fce2f8df6c499cc1c763e4394b7482525bf2a9701c9d79d215f519e4" dependencies = [ - "bitflags 1.3.2", + "bitflags", "cfg-if", + "cfg_aliases", "libc", - "memoffset", - "pin-utils", - "static_assertions", ] [[package]] @@ -886,11 +902,17 @@ dependencies = [ "minimal-lexical", ] +[[package]] +name = "num-conv" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "51d515d32fb182ee37cda2ccdcb92950d6a3c2893aa280e540671c2cd0f3b1d9" + [[package]] name = "num-traits" -version = "0.2.16" +version = "0.2.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f30b0abd723be7e2ffca1272140fac1a2f084c77ec3e123c192b66af1ee9e6c2" +checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" dependencies = [ "autocfg", ] @@ -907,56 +929,50 @@ dependencies = [ [[package]] name = "object" -version = "0.31.1" +version = "0.32.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8bda667d9f2b5051b8833f59f3bf748b28ef54f850f4fcb389a252aa383866d1" +checksum = "a6a622008b6e321afc04970976f62ee297fdbaa6f95318ca343e3eebb9648441" dependencies = [ "memchr", ] [[package]] name = "once_cell" -version = "1.18.0" +version = "1.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d" - -[[package]] -name = "peeking_take_while" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "19b17cddbe7ec3f8bc800887bab5e717348c95ea2ca0b1bf0837fb964dc67099" +checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" [[package]] name = "percent-encoding" -version = "2.3.0" +version = "2.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b2a4787296e9989611394c33f193f676704af1686e70b8f8033ab5ba9a35a94" +checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" [[package]] name = "pin-project" -version = "1.1.2" +version = "1.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "030ad2bc4db10a8944cb0d837f158bdfec4d4a4873ab701a95046770d11f8842" +checksum = "b6bf43b791c5b9e34c3d182969b4abb522f9343702850a2e57f460d00d09b4b3" dependencies = [ "pin-project-internal", ] [[package]] name = "pin-project-internal" -version = "1.1.2" +version = "1.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec2e072ecce94ec471b13398d5402c188e76ac03cf74dd1a975161b23a3f6d9c" +checksum = "2f38a4412a78282e09a2cf38d195ea5420d15ba0602cb375210efbc877243965" dependencies = [ "proc-macro2", "quote", - "syn 2.0.27", + "syn", ] [[package]] name = "pin-project-lite" -version = "0.2.10" +version = "0.2.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c40d25201921e5ff0c862a505c6557ea88568a4e3ace775ab55e93f2f4f9d57" +checksum = "bda66fc9667c18cb2758a2ac84d1167245054bcf85d5d1aaa6923f45801bdd02" [[package]] name = "pin-utils" @@ -964,15 +980,20 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" +[[package]] +name = "powerfmt" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391" + [[package]] name = "predicates" -version = "3.0.3" +version = "3.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09963355b9f467184c04017ced4a2ba2d75cbcb4e7462690d388233253d4b1a9" +checksum = "68b87bfd4605926cdfefc1c3b5f8fe560e3feca9d5552cf68c466d3d8236c7e8" dependencies = [ "anstyle", "difflib", - "itertools", "predicates-core", ] @@ -994,51 +1015,53 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.66" +version = "1.0.82" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "18fb31db3f9bddb2ea821cde30a9f70117e3f119938b5ee630b7403aa6e2ead9" +checksum = "8ad3d49ab951a01fbaafe34f2ec74122942fe18a3f9814c3268f1bb72042131b" dependencies = [ "unicode-ident", ] [[package]] name = "procfs" -version = "0.15.1" +version = "0.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "943ca7f9f29bab5844ecd8fdb3992c5969b6622bb9609b9502fef9b4310e3f1f" +checksum = "731e0d9356b0c25f16f33b5be79b1c57b562f141ebfcdb0ad8ac2c13a24293b4" dependencies = [ - "bitflags 1.3.2", - "byteorder", + "bitflags", "chrono", "flate2", "hex", "lazy_static", - "rustix 0.36.16", + "procfs-core", + "rustix", ] [[package]] -name = "quote" -version = "1.0.32" +name = "procfs-core" +version = "0.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "50f3b39ccfb720540debaa0164757101c08ecb8d326b15358ce76a62c7e85965" +checksum = "2d3554923a69f4ce04c4a754260c338f505ce22642d3830e049a399fc2059a29" dependencies = [ - "proc-macro2", + "bitflags", + "chrono", + "hex", ] [[package]] -name = "redox_syscall" -version = "0.3.5" +name = "quote" +version = "1.0.36" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "567664f262709473930a4bf9e51bf2ebf3348f2e748ccc50dea20646858f8f29" +checksum = "0fa76aaf39101c457836aec0ce2316dbdc3ab723cdda1c6bd4e6ad4208acaca7" dependencies = [ - "bitflags 1.3.2", + "proc-macro2", ] [[package]] name = "regex" -version = "1.9.1" +version = "1.10.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b2eae68fc220f7cf2532e4494aded17545fce192d59cd996e0fe7887f4ceb575" +checksum = "c117dbdfde9c8308975b6a18d71f3f385c89461f7b3fb054288ecf2a2058ba4c" dependencies = [ "aho-corasick", "memchr", @@ -1048,9 +1071,9 @@ dependencies = [ [[package]] name = "regex-automata" -version = "0.3.3" +version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "39354c10dd07468c2e73926b23bb9c2caca74c5501e38a35da70406f1d923310" +checksum = "86b83b8b9847f9bf95ef68afb0b8e6cdb80f498442f5179a29fad448fcc1eaea" dependencies = [ "aho-corasick", "memchr", @@ -1059,15 +1082,15 @@ dependencies = [ [[package]] name = "regex-syntax" -version = "0.7.4" +version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e5ea92a5b6195c6ef2a0295ea818b312502c6fc94dde986c5553242e18fd4ce2" +checksum = "adad44e29e4c806119491a7f06f03de4d1af22c3a680dd47f1e6e179439d1f56" [[package]] name = "rustc-demangle" -version = "0.1.23" +version = "0.1.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76" +checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f" [[package]] name = "rustc-hash" @@ -1077,62 +1100,48 @@ checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" [[package]] name = "rustix" -version = "0.36.16" +version = "0.38.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6da3636faa25820d8648e0e31c5d519bbb01f72fdf57131f0f5f7da5fed36eab" +checksum = "70dc5ec042f7a43c4a73241207cecc9873a06d45debb38b329f8541d85c2730f" dependencies = [ - "bitflags 1.3.2", - "errno 0.3.1", - "io-lifetimes", + "bitflags", + "errno", "libc", - "linux-raw-sys 0.1.4", - "windows-sys 0.45.0", -] - -[[package]] -name = "rustix" -version = "0.38.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0a962918ea88d644592894bc6dc55acc6c0956488adcebbfb6e273506b7fd6e5" -dependencies = [ - "bitflags 2.3.3", - "errno 0.3.1", - "libc", - "linux-raw-sys 0.4.3", - "windows-sys 0.48.0", + "linux-raw-sys", + "windows-sys 0.52.0", ] [[package]] name = "ryu" -version = "1.0.15" +version = "1.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ad4cc8da4ef723ed60bced201181d83791ad433213d8c24efffda1eec85d741" +checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f" [[package]] name = "serde" -version = "1.0.175" +version = "1.0.202" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5d25439cd7397d044e2748a6fe2432b5e85db703d6d097bd014b3c0ad1ebff0b" +checksum = "226b61a0d411b2ba5ff6d7f73a476ac4f8bb900373459cd00fab8512828ba395" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.175" +version = "1.0.202" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b23f7ade6f110613c0d63858ddb8b94c1041f550eab58a16b371bdf2c9c80ab4" +checksum = "6048858004bcff69094cd972ed40a32500f153bd3be9f716b2eed2e8217c4838" dependencies = [ "proc-macro2", "quote", - "syn 2.0.27", + "syn", ] [[package]] name = "serde_json" -version = "1.0.104" +version = "1.0.117" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "076066c5f1078eac5b722a31827a8832fe108bed65dfa75e233c89f8206e976c" +checksum = "455182ea6142b14f93f4bc5320a2b31c1f266b66a4a5c858b013302a5d8cbfc3" dependencies = [ "itoa", "ryu", @@ -1141,13 +1150,13 @@ dependencies = [ [[package]] name = "serde_repr" -version = "0.1.15" +version = "0.1.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e168eaaf71e8f9bd6037feb05190485708e019f4fd87d161b3c0a0d37daf85e5" +checksum = "6c64451ba24fc7a6a2d60fc75dd9c83c90903b19028d4eff35e88fc1e86564e9" dependencies = [ "proc-macro2", "quote", - "syn 2.0.27", + "syn", ] [[package]] @@ -1164,15 +1173,17 @@ dependencies = [ [[package]] name = "serde_with" -version = "2.3.3" +version = "3.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07ff71d2c147a7b57362cead5e22f772cd52f6ab31cfcd9edcd7f6aeb2a0afbe" +checksum = "0ad483d2ab0149d5a5ebcd9972a3852711e0153d863bf5a5d0391d28883c4a20" dependencies = [ - "base64 0.13.1", + "base64", "chrono", "hex", "indexmap 1.9.3", + "indexmap 2.2.6", "serde", + "serde_derive", "serde_json", "time", ] @@ -1185,51 +1196,40 @@ checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" [[package]] name = "slab" -version = "0.4.8" +version = "0.4.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6528351c9bc8ab22353f9d776db39a20288e8d6c37ef8cfe3317cf875eecfc2d" +checksum = "8f92a496fb766b417c996b9c5e57daf2f7ad3b0bebe1ccfca4856390e3d3bb67" dependencies = [ "autocfg", ] +[[package]] +name = "smallvec" +version = "1.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" + [[package]] name = "socket2" -version = "0.4.9" +version = "0.5.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "64a4a911eed85daf18834cfaa86a79b7d266ff93ff5ba14005426219480ed662" +checksum = "ce305eb0b4296696835b71df73eb912e0f1ffd2556a501fcede6e0c50349191c" dependencies = [ "libc", - "winapi", + "windows-sys 0.52.0", ] -[[package]] -name = "static_assertions" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" - [[package]] name = "strsim" -version = "0.10.0" +version = "0.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" +checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" [[package]] name = "syn" -version = "1.0.109" +version = "2.0.63" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" -dependencies = [ - "proc-macro2", - "quote", - "unicode-ident", -] - -[[package]] -name = "syn" -version = "2.0.27" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b60f673f44a8255b9c8c657daf66a596d435f2da81a555b06dc644d080ba45e0" +checksum = "bf5be731623ca1a1fb7d8be6f261a3be6d3e2337b8a1f97be944d020c8fcb704" dependencies = [ "proc-macro2", "quote", @@ -1238,24 +1238,14 @@ dependencies = [ [[package]] name = "tempfile" -version = "3.7.0" +version = "3.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5486094ee78b2e5038a6382ed7645bc084dc2ec433426ca4c3cb61e2007b8998" +checksum = "85b77fafb263dd9d05cbeac119526425676db3784113aa9295c88498cbf8bff1" dependencies = [ "cfg-if", "fastrand", - "redox_syscall", - "rustix 0.38.4", - "windows-sys 0.48.0", -] - -[[package]] -name = "termcolor" -version = "1.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be55cf8942feac5c765c2c993422806843c9a9a45d4d5c407ad6dd2ea95eb9b6" -dependencies = [ - "winapi-util", + "rustix", + "windows-sys 0.52.0", ] [[package]] @@ -1266,31 +1256,34 @@ checksum = "3369f5ac52d5eb6ab48c6b4ffdc8efbcad6b89c765749064ba298f2c68a16a76" [[package]] name = "thiserror" -version = "1.0.44" +version = "1.0.60" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "611040a08a0439f8248d1990b111c95baa9c704c805fa1f62104b39655fd7f90" +checksum = "579e9083ca58dd9dcf91a9923bb9054071b9ebbd800b342194c9feb0ee89fc18" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.44" +version = "1.0.60" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "090198534930841fab3a5d1bb637cde49e339654e606195f8d9c76eeb081dc96" +checksum = "e2470041c06ec3ac1ab38d0356a6119054dedaea53e12fbefc0de730a1c08524" dependencies = [ "proc-macro2", "quote", - "syn 2.0.27", + "syn", ] [[package]] name = "time" -version = "0.3.23" +version = "0.3.36" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "59e399c068f43a5d116fedaf73b203fa4f9c519f17e2b34f63221d3792f81446" +checksum = "5dfd88e563464686c916c7e46e623e520ddc6d79fa6641390f2e3fa86e83e885" dependencies = [ + "deranged", "itoa", + "num-conv", + "powerfmt", "serde", "time-core", "time-macros", @@ -1298,16 +1291,17 @@ dependencies = [ [[package]] name = "time-core" -version = "0.1.1" +version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7300fbefb4dadc1af235a9cef3737cea692a9d97e1b9cbcd4ebdae6f8868e6fb" +checksum = "ef927ca75afb808a4d64dd374f00a2adf8d0fcff8e7b184af886c3c87ec4a3f3" [[package]] name = "time-macros" -version = "0.2.10" +version = "0.2.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96ba15a897f3c86766b757e5ac7221554c6750054d74d5b28844fce5fb36a6c4" +checksum = "3f252a68540fde3a3877aeea552b832b40ab9a69e318efd078774a01ddee1ccf" dependencies = [ + "num-conv", "time-core", ] @@ -1328,11 +1322,10 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] name = "tokio" -version = "1.29.1" +version = "1.37.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "532826ff75199d5833b9d2c5fe410f29235e25704ee5f0ef599fb51c21f4a4da" +checksum = "1adbebffeca75fcfd058afa480fb6c0b81e165a0323f9c9d39c9697e37c46787" dependencies = [ - "autocfg", "backtrace", "bytes", "libc", @@ -1345,18 +1338,39 @@ dependencies = [ [[package]] name = "tokio-util" -version = "0.7.8" +version = "0.7.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "806fe8c2c87eccc8b3267cbae29ed3ab2d0bd37fca70ab622e46aaa9375ddb7d" +checksum = "9cf6b47b3771c49ac75ad09a6162f53ad4b8088b76ac60e8ec1455b31a189fe1" dependencies = [ "bytes", "futures-core", "futures-sink", "pin-project-lite", "tokio", +] + +[[package]] +name = "tower" +version = "0.4.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8fa9be0de6cf49e536ce1851f987bd21a43b771b09473c3549a6c853db37c1c" +dependencies = [ + "futures-core", + "futures-util", + "pin-project", + "pin-project-lite", + "tokio", + "tower-layer", + "tower-service", "tracing", ] +[[package]] +name = "tower-layer" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c20c8dbed6283a09604c3e69b4b7eeb54e298b8a600d4d5ecb5ad39de609f1d0" + [[package]] name = "tower-service" version = "0.3.2" @@ -1365,56 +1379,56 @@ checksum = "b6bc1c9ce2b5135ac7f93c72918fc37feb872bdc6a5533a8b85eb4b86bfdae52" [[package]] name = "tracing" -version = "0.1.37" +version = "0.1.40" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ce8c33a8d48bd45d624a6e523445fd21ec13d3653cd51f681abf67418f54eb8" +checksum = "c3523ab5a71916ccf420eebdf5521fcef02141234bbc0b8a49f2fdc4544364ef" dependencies = [ - "cfg-if", + "log", "pin-project-lite", "tracing-core", ] [[package]] name = "tracing-core" -version = "0.1.31" +version = "0.1.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0955b8137a1df6f1a2e9a37d8a6656291ff0297c1a97c24e0d8425fe2312f79a" +checksum = "c06d3da6113f116aaee68e4d601191614c9053067f9ab7f6edbcb161237daa54" dependencies = [ "once_cell", ] [[package]] name = "try-lock" -version = "0.2.4" +version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3528ecfd12c466c6f163363caf2d02a71161dd5e1cc6ae7b34207ea2d42d81ed" +checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b" [[package]] name = "unicode-bidi" -version = "0.3.13" +version = "0.3.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "92888ba5573ff080736b3648696b70cafad7d250551175acbaa4e0385b3e1460" +checksum = "08f95100a766bf4f8f28f90d77e0a5461bbdb219042e7679bebe79004fed8d75" [[package]] name = "unicode-ident" -version = "1.0.11" +version = "1.0.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "301abaae475aa91687eb82514b328ab47a211a533026cb25fc3e519b86adfc3c" +checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" [[package]] name = "unicode-normalization" -version = "0.1.22" +version = "0.1.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c5713f0fc4b5db668a2ac63cdb7bb4469d8c9fed047b1d0292cc7b0ce2ba921" +checksum = "a56d1686db2308d901306f92a263857ef59ea39678a5458e7cb17f01415101f5" dependencies = [ "tinyvec", ] [[package]] name = "url" -version = "2.4.0" +version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "50bff7831e19200a85b17131d085c25d7811bc4e186efdaf54bbd132994a88cb" +checksum = "31e6302e3bb753d46e83516cae55ae196fc0c309407cf11ab35cc51a4c2a4633" dependencies = [ "form_urlencoded", "idna", @@ -1453,9 +1467,9 @@ checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" [[package]] name = "wasm-bindgen" -version = "0.2.87" +version = "0.2.92" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7706a72ab36d8cb1f80ffbf0e071533974a60d0a308d01a5d0375bf60499a342" +checksum = "4be2531df63900aeb2bca0daaaddec08491ee64ceecbee5076636a3b026795a8" dependencies = [ "cfg-if", "wasm-bindgen-macro", @@ -1463,24 +1477,24 @@ dependencies = [ [[package]] name = "wasm-bindgen-backend" -version = "0.2.87" +version = "0.2.92" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ef2b6d3c510e9625e5fe6f509ab07d66a760f0885d858736483c32ed7809abd" +checksum = "614d787b966d3989fa7bb98a654e369c762374fd3213d212cfc0251257e747da" dependencies = [ "bumpalo", "log", "once_cell", "proc-macro2", "quote", - "syn 2.0.27", + "syn", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-macro" -version = "0.2.87" +version = "0.2.92" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dee495e55982a3bd48105a7b947fd2a9b4a8ae3010041b9e0faab3f9cd028f1d" +checksum = "a1f8823de937b71b9460c0c34e25f3da88250760bec0ebac694b49997550d726" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -1488,22 +1502,22 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.87" +version = "0.2.92" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "54681b18a46765f095758388f2d0cf16eb8d4169b639ab575a8f5693af210c7b" +checksum = "e94f17b526d0a461a191c78ea52bbce64071ed5c04c9ffe424dcb38f74171bb7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.27", + "syn", "wasm-bindgen-backend", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-shared" -version = "0.2.87" +version = "0.2.92" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca6ad05a4870b2bf5fe995117d3728437bd27d7cd5f06f13c17443ef369775a1" +checksum = "af190c94f2773fdb3729c55b007a722abb5384da03bc0986df4c289bf5567e96" [[package]] name = "winapi" @@ -1521,15 +1535,6 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" -[[package]] -name = "winapi-util" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178" -dependencies = [ - "winapi", -] - [[package]] name = "winapi-x86_64-pc-windows-gnu" version = "0.4.0" @@ -1537,142 +1542,149 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" [[package]] -name = "windows" -version = "0.48.0" +name = "windows-core" +version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e686886bc078bc1b0b600cac0147aadb815089b6e4da64016cbd754b6342700f" +checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9" dependencies = [ - "windows-targets 0.48.1", + "windows-targets 0.52.5", ] [[package]] name = "windows-sys" -version = "0.45.0" +version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "75283be5efb2831d37ea142365f009c02ec203cd29a3ebecbc093d52315b66d0" +checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" dependencies = [ - "windows-targets 0.42.2", + "windows-targets 0.48.5", ] [[package]] name = "windows-sys" -version = "0.48.0" +version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" +checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" dependencies = [ - "windows-targets 0.48.1", + "windows-targets 0.52.5", ] [[package]] name = "windows-targets" -version = "0.42.2" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e5180c00cd44c9b1c88adb3693291f1cd93605ded80c250a75d472756b4d071" +checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c" dependencies = [ - "windows_aarch64_gnullvm 0.42.2", - "windows_aarch64_msvc 0.42.2", - "windows_i686_gnu 0.42.2", - "windows_i686_msvc 0.42.2", - "windows_x86_64_gnu 0.42.2", - "windows_x86_64_gnullvm 0.42.2", - "windows_x86_64_msvc 0.42.2", + "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.48.1" +version = "0.52.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05d4b17490f70499f20b9e791dcf6a299785ce8af4d709018206dc5b4953e95f" +checksum = "6f0713a46559409d202e70e28227288446bf7841d3211583a4b53e3f6d96e7eb" dependencies = [ - "windows_aarch64_gnullvm 0.48.0", - "windows_aarch64_msvc 0.48.0", - "windows_i686_gnu 0.48.0", - "windows_i686_msvc 0.48.0", - "windows_x86_64_gnu 0.48.0", - "windows_x86_64_gnullvm 0.48.0", - "windows_x86_64_msvc 0.48.0", + "windows_aarch64_gnullvm 0.52.5", + "windows_aarch64_msvc 0.52.5", + "windows_i686_gnu 0.52.5", + "windows_i686_gnullvm", + "windows_i686_msvc 0.52.5", + "windows_x86_64_gnu 0.52.5", + "windows_x86_64_gnullvm 0.52.5", + "windows_x86_64_msvc 0.52.5", ] [[package]] name = "windows_aarch64_gnullvm" -version = "0.42.2" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "597a5118570b68bc08d8d59125332c54f1ba9d9adeedeef5b99b02ba2b0698f8" +checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" [[package]] name = "windows_aarch64_gnullvm" -version = "0.48.0" +version = "0.52.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "91ae572e1b79dba883e0d315474df7305d12f569b400fcf90581b06062f7e1bc" +checksum = "7088eed71e8b8dda258ecc8bac5fb1153c5cffaf2578fc8ff5d61e23578d3263" [[package]] name = "windows_aarch64_msvc" -version = "0.42.2" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e08e8864a60f06ef0d0ff4ba04124db8b0fb3be5776a5cd47641e942e58c4d43" +checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" [[package]] name = "windows_aarch64_msvc" -version = "0.48.0" +version = "0.52.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b2ef27e0d7bdfcfc7b868b317c1d32c641a6fe4629c171b8928c7b08d98d7cf3" +checksum = "9985fd1504e250c615ca5f281c3f7a6da76213ebd5ccc9561496568a2752afb6" [[package]] name = "windows_i686_gnu" -version = "0.42.2" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c61d927d8da41da96a81f029489353e68739737d3beca43145c8afec9a31a84f" +checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" [[package]] name = "windows_i686_gnu" -version = "0.48.0" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "88ba073cf16d5372720ec942a8ccbf61626074c6d4dd2e745299726ce8b89670" + +[[package]] +name = "windows_i686_gnullvm" +version = "0.52.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "622a1962a7db830d6fd0a69683c80a18fda201879f0f447f065a3b7467daa241" +checksum = "87f4261229030a858f36b459e748ae97545d6f1ec60e5e0d6a3d32e0dc232ee9" [[package]] name = "windows_i686_msvc" -version = "0.42.2" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "44d840b6ec649f480a41c8d80f9c65108b92d89345dd94027bfe06ac444d1060" +checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" [[package]] name = "windows_i686_msvc" -version = "0.48.0" +version = "0.52.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4542c6e364ce21bf45d69fdd2a8e455fa38d316158cfd43b3ac1c5b1b19f8e00" +checksum = "db3c2bf3d13d5b658be73463284eaf12830ac9a26a90c717b7f771dfe97487bf" [[package]] name = "windows_x86_64_gnu" -version = "0.42.2" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8de912b8b8feb55c064867cf047dda097f92d51efad5b491dfb98f6bbb70cb36" +checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" [[package]] name = "windows_x86_64_gnu" -version = "0.48.0" +version = "0.52.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca2b8a661f7628cbd23440e50b05d705db3686f894fc9580820623656af974b1" +checksum = "4e4246f76bdeff09eb48875a0fd3e2af6aada79d409d33011886d3e1581517d9" [[package]] name = "windows_x86_64_gnullvm" -version = "0.42.2" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26d41b46a36d453748aedef1486d5c7a85db22e56aff34643984ea85514e94a3" +checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" [[package]] name = "windows_x86_64_gnullvm" -version = "0.48.0" +version = "0.52.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7896dbc1f41e08872e9d5e8f8baa8fdd2677f29468c4e156210174edc7f7b953" +checksum = "852298e482cd67c356ddd9570386e2862b5673c85bd5f88df9ab6802b334c596" [[package]] name = "windows_x86_64_msvc" -version = "0.42.2" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9aec5da331524158c6d1a4ac0ab1541149c0b9505fde06423b02f5ef0106b9f0" +checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" [[package]] name = "windows_x86_64_msvc" -version = "0.48.0" +version = "0.52.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a515f5799fe4961cb532f983ce2b23082366b898e52ffbce459c86f67c8378a" +checksum = "bec47e5bfd1bff0eeaf6d8b485cc1074891a197ab4225d504cb7a1ab88b02bf0" diff --git a/Cargo.toml b/Cargo.toml index 1b5dfc7..98d84f8 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,10 +1,10 @@ [package] name = "killport" -version = "0.9.2" +version = "1.0.0" authors = ["Francisco Jimenez Cabrera "] edition = "2021" license = "MIT" -description = "A command-line tool to easily kill processes running on a specified port." +description = "A command-line tool to easily kill processes and containers running on a specified port." readme = "README.md" homepage = "https://github.com/jkfran/killport" repository = "https://github.com/jkfran/killport" @@ -12,23 +12,22 @@ keywords = ["cli", "port", "process", "kill", "linux"] categories = ["command-line-utilities"] [dependencies] -log = "0.4.19" -env_logger = "0.10.0" -clap-verbosity-flag = "2.0.1" -clap = { version = "4.3.19", features = ["derive"] } -nix = "0.26.2" -bollard = "0.14.0" -tokio = "1.29.1" +log = "0.4.21" +env_logger = "0.11.3" +clap-verbosity-flag = "2.2.0" +clap = { version = "4.5.4", features = ["derive"] } +nix = { version = "0.28.0", features = ["signal"] } +bollard = "0.16.1" +tokio = { version = "1.37.0", features = ["rt-multi-thread"] } [target.'cfg(any(target_os = "linux", target_os = "android"))'.dependencies] -procfs = "0.15.1" +procfs = "0.16.0" [target.'cfg(target_os = "macos")'.dependencies] -libproc = "0.13.0" -libc = "0.2" +libproc = "0.14.8" [target.'cfg(target_os = "windows")'.dependencies.windows-sys] -version = "0.48" +version = "0.52" features = [ "Win32_Foundation", "Win32_NetworkManagement_IpHelper", @@ -38,5 +37,6 @@ features = [ ] [dev-dependencies] -assert_cmd = "2.0.12" -tempfile = "3.7.0" +assert_cmd = "2.0.14" +tempfile = "3.10.1" +mockall = "0.12.1" diff --git a/README.md b/README.md index 335941c..886c7d3 100644 --- a/README.md +++ b/README.md @@ -10,16 +10,16 @@ # killport -`killport` is a command-line utility for killing processes listening on specific ports. It's designed to be simple, fast, and effective. The tool is built with Rust and works on Linux, macOS, and Windows. +`killport` is a command-line utility designed for efficiently terminating processes and containers listening on specified ports. It supports both single and multiple port operations, enhancing system management across Linux, macOS, and Windows platforms. Built with Rust, `killport` combines flexibility with performance in process management tasks. ## Features -- Kill processes by port number -- Kill docker container by port number -- Supports multiple port numbers -- Verbosity control -- Works on Linux, macOS and Windows -- Serveral signal types (SIGTERM, SIGKILL) +- Terminate processes or containers on specified ports with support for single or multiple ports. +- Mode of operation options to target either processes, containers, or both. +- Dry-run capability for safe operations without actual termination. +- Adjustable verbosity for detailed logging and quiet operation for minimal output. +- Comprehensive signal support for fine-grained control over the termination signals sent to processes or containers. +- Cross-platform compatibility: Linux, macOS, and Windows. ## Installation @@ -56,77 +56,74 @@ You can download the binary releases for different architectures from the [relea ## Usage ```sh -killport [FLAGS] ... +killport [OPTIONS] ... ``` +### Flags + +- `-m, --mode `: Select mode of operation (process, container, or both). +- `-s, --signal `: Specify the signal to send (default: SIGKILL). +- `-v, --verbose`: Increase verbosity level (use multiple times for more detail). +- `-q, --quiet`: Decrease verbosity level (use multiple times for less detail). +- `--dry-run`: Preview which processes or containers would be terminated. +- `-h, --help`: Display help message. +- `-V, --version`: Display version information. + ### Examples -Kill a single process listening on port 8080: +Kill a single process on port 8080: ```sh killport 8080 ``` -Kill multiple processes listening on ports 8045, 8046, and 8080: +Kill processes on multiple ports with a specific signal: ```sh -killport 8045 8046 8080 +killport -s sigterm 8045 8046 8080 ``` -Kill processes with specified signal: +Perform a dry run to check what would be killed on port 8080: ```sh -killport -s sigkill 8080 +killport --dry-run 8080 ``` Supported Signals: -- sighup -- sigint -- sigquit -- sigill -- sigtrap -- sigabrt -- sigbus -- sigfpe -- sigkill -- sigusr1 -- sigsegv -- sigusr2 -- sigpipe -- sigalrm -- sigterm -- sigstkflt -- sigchld -- sigcont -- sigstop -- sigtstp -- sigttin -- sigttou -- sigurg -- sigxcpu -- sigxfsz -- sigvtalrm -- sigprof -- sigwinch -- sigio -- sigpwr -- sigsys -- sigemt -- siginfo - -### Flags - --s, --signal - Specify a signal name to be sent. (e.g. sigkill) - --v, --verbose - Increase the verbosity level. Use multiple times for more detailed output. - --h, --help - Display the help message and exit. --V, --version - Display the version information and exit. +1. **Softest/Lower Preference Signals (Generally ignorable or default to terminate the process gently):** + - `SIGUSR1` - User-defined signal 1 + - `SIGUSR2` - User-defined signal 2 + - `SIGWINCH` - Window size change + - `SIGURG` - Urgent condition on socket + - `SIGCONT` - Continue if stopped + - `SIGCHLD` - Child status has changed + - `SIGIO` - I/O now possible + - `SIGALRM` - Timer signal + - `SIGVTALRM` - Virtual timer expired + - `SIGPROF` - Profiling timer expired + - `SIGPWR` - Power failure + - `SIGSYS` - Bad argument to routine + - `SIGPIPE` - Broken pipe: write to pipe with no readers + - `SIGTERM` - Termination signal + - `SIGHUP` - Hangup detected on controlling terminal or death of controlling process + - `SIGINT` - This signal is sent to a process by its controlling terminal when a user wishes to interrupt the process. + +2. **Higher Preference/More Disruptive Signals (Generally not ignorable and often default to terminate the process abruptly):** + - `SIGQUIT` - Quit from keyboard and dump core + - `SIGABRT` - Abort signal from abort() + - `SIGTSTP` - Stop typed at terminal + - `SIGTTIN` - Terminal input for background process + - `SIGTTOU` - Terminal output for background process + - `SIGSTOP` - Stop process + - `SIGSEGV` - Invalid memory reference + - `SIGBUS` - Bus error (bad memory access) + - `SIGFPE` - Floating-point exception + - `SIGILL` - Illegal Instruction + - `SIGTRAP` - Trace/breakpoint trap + +3. **Most Severe/Definitive Signals (Cannot be caught or ignored):** + - `SIGKILL` - Kill signal ## Contributing diff --git a/snapcraft.yaml b/snapcraft.yaml index e670ac5..35c3415 100644 --- a/snapcraft.yaml +++ b/snapcraft.yaml @@ -1,5 +1,5 @@ name: killport -version: "0.9.2" +version: "1.0.0" summary: A CLI tool to kill processes using specified ports description: | Killport is a command-line utility to find and kill processes listening on specified ports. diff --git a/src/cli.rs b/src/cli.rs new file mode 100644 index 0000000..7e01424 --- /dev/null +++ b/src/cli.rs @@ -0,0 +1,94 @@ +use clap::{Parser, ValueEnum}; +use clap_verbosity_flag::{Verbosity, WarnLevel}; +use core::fmt; +use nix::sys::signal::Signal; +use std::str::FromStr; + +/// Modes of operation for killport. +#[derive(Debug, Clone, Copy, PartialEq, ValueEnum)] +pub enum Mode { + Auto, + Process, + Container, +} + +impl fmt::Display for Mode { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + let variant = match *self { + Mode::Auto => "auto", + Mode::Process => "process", + Mode::Container => "container", + }; + write!(f, "{}", variant) + } +} + +/// Returns appropriate service descriptors based on the mode. +/// +/// # Arguments +/// * `mode` - The mode of operation. +/// +/// # Returns +/// * `(singular, plural)` - Tuple containing singular and plural forms of the service description. +pub fn service_descriptors(mode: Mode) -> (&'static str, &'static str) { + match mode { + Mode::Auto => ("service", "services"), + Mode::Process => ("process", "processes"), + Mode::Container => ("container", "containers"), + } +} + +/// `killport` utility. +#[derive(Parser, Debug)] +#[command(author, version, about, long_about = None)] +pub struct KillPortArgs { + /// A list of port numbers to kill processes on. + #[arg( + name = "ports", + help = "The list of port numbers to kill processes or containers on", + required = true + )] + pub ports: Vec, + + /// Operation mode. + #[arg( + long, + short = 'm', + help = "Mode of operation: auto (default, kill both), process (only processes), container (only containers)", + default_value_t = Mode::Auto)] + pub mode: Mode, + + /// An option to specify the type of signal to be sent. + #[arg( + long, + short = 's', + name = "SIG", + help = "SIG is a signal name", + default_value = "sigkill", + value_parser = parse_signal + )] + pub signal: Signal, + + /// A verbosity flag to control the level of logging output. + #[command(flatten)] + pub verbose: Verbosity, + + /// Dry-run flag to only display what would be done without taking action. + #[arg( + long, + help = "Perform a dry run without killing any processes or containers" + )] + pub dry_run: bool, +} + +fn parse_signal(arg: &str) -> Result { + let str_arg = arg.parse::(); + match str_arg { + Ok(str_arg) => { + let signal_str = str_arg.to_uppercase(); + let signal = Signal::from_str(signal_str.as_str())?; + return Ok(signal); + } + Err(e) => Err(std::io::Error::new(std::io::ErrorKind::Other, e)), + } +} diff --git a/src/docker.rs b/src/docker.rs new file mode 100644 index 0000000..1a4f3f1 --- /dev/null +++ b/src/docker.rs @@ -0,0 +1,96 @@ +use bollard::container::{KillContainerOptions, ListContainersOptions}; +use bollard::Docker; +use log::debug; +use nix::sys::signal::Signal; +use std::collections::HashMap; +use std::io::Error; +use tokio::runtime::Runtime; + +pub struct DockerContainer { + pub name: String, +} + +impl DockerContainer { + /// Kill the docker container. + /// + /// # Arguments + /// + /// * `name` - A container name. + /// * `signal` - A enum value representing the signal type. + pub fn kill_container(name: &String, signal: Signal) -> Result<(), Error> { + let rt = Runtime::new()?; + rt.block_on(async { + let docker = Docker::connect_with_socket_defaults() + .map_err(|e| Error::new(std::io::ErrorKind::Other, e.to_string()))?; + + let options = KillContainerOptions { + signal: signal.to_string(), + }; + + docker + .kill_container(name, Some(options)) + .await + .map_err(|e| Error::new(std::io::ErrorKind::Other, e.to_string())) + }) + } + + /// Finds the Docker containers associated with the specified `port`. + pub fn find_target_containers(port: u16) -> Result, Error> { + let rt = Runtime::new()?; + rt.block_on(async { + let docker = Docker::connect_with_socket_defaults() + .map_err(|e| Error::new(std::io::ErrorKind::Other, e.to_string()))?; + + let mut filters = HashMap::new(); + filters.insert("publish".to_string(), vec![port.to_string()]); + filters.insert("status".to_string(), vec!["running".to_string()]); + + let options = ListContainersOptions { + filters, + ..Default::default() + }; + + let containers = docker + .list_containers::(Some(options)) + .await + .map_err(|e| Error::new(std::io::ErrorKind::Other, e.to_string()))?; + + Ok(containers + .iter() + .filter_map(|container| { + container + .names + .as_ref()? + .first() + .map(|name| DockerContainer { + name: if name.starts_with('/') { + name[1..].to_string() + } else { + name.clone() + }, + }) + }) + .collect()) + }) + } + + pub fn is_docker_present() -> Result { + let rt = Runtime::new()?; + rt.block_on(async { + let docker = Docker::connect_with_socket_defaults() + .map_err(|e| Error::new(std::io::ErrorKind::Other, e.to_string()))?; + + // Attempt to get the Docker version as a test of connectivity. + match docker.version().await { + Ok(version) => { + debug!("Connected to Docker version: {:?}", version); + Ok(true) + } + Err(e) => { + debug!("Failed to connect to Docker: {}", e); + Ok(false) + } + } + }) + } +} diff --git a/src/killport.rs b/src/killport.rs new file mode 100644 index 0000000..a17e7c8 --- /dev/null +++ b/src/killport.rs @@ -0,0 +1,190 @@ +use crate::cli::Mode; +use crate::docker::DockerContainer; +#[cfg(target_os = "linux")] +use crate::linux::find_target_processes; +#[cfg(target_os = "macos")] +use crate::macos::find_target_processes; +use log::info; +use nix::sys::signal::{kill, Signal}; +use nix::unistd::Pid; +use std::io::Error; + +#[derive(Debug)] +pub struct NativeProcess { + /// System native process ID. + pub pid: Pid, + pub name: String, +} + +/// Interface for killable targets such as native process and docker container. +pub trait Killable { + fn kill(&self, signal: Signal) -> Result; + fn get_type(&self) -> String; + fn get_name(&self) -> String; +} + +impl Killable for NativeProcess { + /// Entry point to kill the linux native process. + /// + /// # Arguments + /// + /// * `signal` - A enum value representing the signal type. + fn kill(&self, signal: Signal) -> Result { + info!("Killing process '{}' with PID {}", self.name, self.pid); + + kill(self.pid, signal).map(|_| true).map_err(|e| { + Error::new( + std::io::ErrorKind::Other, + format!( + "Failed to kill process '{}' with PID {}: {}", + self.name, self.pid, e + ), + ) + }) + } + + /// Returns the type of the killable target. + /// + /// This method is used to identify the type of the target (either a native process or a Docker container) + /// that is being handled. This information can be useful for logging, error handling, or other needs + /// where type of the target is relevant. + /// + /// # Returns + /// + /// * `String` - A string that describes the type of the killable target. For a `NativeProcess` it will return "process", + /// and for a `DockerContainer` it will return "container". + fn get_type(&self) -> String { + "process".to_string() + } + + fn get_name(&self) -> String { + self.name.to_string() + } +} + +impl Killable for DockerContainer { + /// Entry point to kill the docker containers. + /// + /// # Arguments + /// + /// * `signal` - A enum value representing the signal type. + fn kill(&self, signal: Signal) -> Result { + if let Err(err) = Self::kill_container(&self.name, signal) { + return Err(err); + } + + Ok(true) + } + + /// Returns the type of the killable target. + /// + /// This method is used to identify the type of the target (either a native process or a Docker container) + /// that is being handled. This information can be useful for logging, error handling, or other needs + /// where type of the target is relevant. + /// + /// # Returns + /// + /// * `String` - A string that describes the type of the killable target. For a `NativeProcess` it will return "process", + /// and for a `DockerContainer` it will return "container". + fn get_type(&self) -> String { + "container".to_string() + } + + fn get_name(&self) -> String { + self.name.to_string() + } +} + +pub trait KillportOperations { + /// Finds the killables (native processes and docker containers) associated with the specified `port`. + fn find_target_killables(&self, port: u16, mode: Mode) + -> Result>, Error>; + + /// Manages the action of killing or simulating the killing of services by port. + fn kill_service_by_port( + &self, + port: u16, + signal: Signal, + mode: Mode, + dry_run: bool, + ) -> Result, Error>; +} + +pub struct Killport; + +impl KillportOperations for Killport { + /// Finds the killables (native processes and docker containers) associated with the specified `port`. + /// + /// Returns a `Vec` of killables. + /// + /// # Arguments + /// + /// * `port` - A u16 value representing the port number. + fn find_target_killables( + &self, + port: u16, + mode: Mode, + ) -> Result>, Error> { + let mut target_killables: Vec> = vec![]; + let docker_present = mode != Mode::Process && DockerContainer::is_docker_present()?; + + if mode != Mode::Container { + let target_processes = find_target_processes(port)?; + + for process in target_processes { + // Check if the process name contains 'docker' and skip if in docker mode + if docker_present && process.name.to_lowercase().contains("docker") { + continue; + } + target_killables.push(Box::new(process)); + } + } + + // Add containers if Docker is present and mode is not set to only process + if docker_present && mode != Mode::Process { + let target_containers = DockerContainer::find_target_containers(port)?; // Assume this function returns Result, Error> + + for container in target_containers { + target_killables.push(Box::new(container)); + } + } + + Ok(target_killables) + } + + /// Manages the action of killing or simulating the killing of services by port. + /// This function can either actually kill processes or containers, or simulate the action based on the `dry_run` flag. + /// + /// # Arguments + /// * `port` - The port number to check for killable entities. + /// * `signal` - The signal to send if not simulating. + /// * `mode` - The mode of operation, determining if processes, containers, or both should be targeted. + /// * `dry_run` - If true, simulates the actions without actually killing any entities. + /// + /// # Returns + /// * `Result, Error>` - A list of killable entities or an error. + fn kill_service_by_port( + &self, + port: u16, + signal: Signal, + mode: Mode, + dry_run: bool, + ) -> Result, Error> { + let mut results = Vec::new(); + let target_killables = self.find_target_killables(port, mode)?; // Use the existing function to find targets + + for killable in target_killables { + if dry_run { + // In dry-run mode, collect information about the entity without killing + results.push((killable.get_type(), killable.get_name())); + } else { + // In actual mode, attempt to kill the entity and collect its information if successful + if killable.kill(signal)? { + results.push((killable.get_type(), killable.get_name())); + } + } + } + + Ok(results) + } +} diff --git a/src/lib.rs b/src/lib.rs new file mode 100644 index 0000000..97f84b9 --- /dev/null +++ b/src/lib.rs @@ -0,0 +1,9 @@ +pub mod cli; +pub mod docker; +pub mod killport; +#[cfg(target_os = "linux")] +pub mod linux; +#[cfg(target_os = "macos")] +pub mod macos; +#[cfg(target_os = "windows")] +pub mod windows; diff --git a/src/linux.rs b/src/linux.rs index b5a6bf0..de0151a 100644 --- a/src/linux.rs +++ b/src/linux.rs @@ -1,244 +1,9 @@ -use bollard::container::{KillContainerOptions, ListContainersOptions}; -use bollard::Docker; -use log::{debug, info, warn}; -use nix::sys::signal::{kill, Signal}; +use crate::killport::NativeProcess; + +use log::debug; use nix::unistd::Pid; use procfs::process::FDTarget; -use std::collections::HashMap; -use std::io; use std::io::Error; -use tokio::runtime::Runtime; - -/// Interface for killable targets such as native process and docker container. -trait Killable { - fn kill(&self, signal: KillPortSignalOptions) -> Result; - fn get_type(&self) -> String; -} - -#[derive(Debug)] -struct NativeProcess { - /// System native process ID. - pid: Pid, -} - -impl NativeProcess { - /// Kills the process with the specified `pid`. - /// - /// # Arguments - /// - /// * `pid` - An Pid struct representing the process ID. - /// * `signal` - A enum value representing the signal type. - fn kill_process(pid: Pid, signal: KillPortSignalOptions) -> Result<(), Error> { - info!("Killing process with PID {}", pid); - - let system_signal = match signal { - KillPortSignalOptions::SIGKILL => Signal::SIGKILL, - KillPortSignalOptions::SIGTERM => Signal::SIGTERM, - }; - kill(pid, system_signal).map_err(|e| std::io::Error::new(std::io::ErrorKind::Other, e)) - } - - /// Recursively kills the process with the specified `pid` and its children. - /// - /// # Arguments - /// - /// * `pid` - An Pid struct representing the process ID. - /// * `signal` - A enum value representing the signal type. - fn kill_process_and_children(pid: Pid, signal: KillPortSignalOptions) -> Result<(), Error> { - let mut children_pids = Vec::new(); - Self::collect_child_pids(pid, &mut children_pids) - .map_err(|e| std::io::Error::new(std::io::ErrorKind::Other, e))?; - - for child_pid in children_pids { - Self::kill_process(child_pid, signal)?; - } - - Self::kill_process(pid, signal)?; - - Ok(()) - } - - /// Collects the child process IDs for the specified `pid` and stores them in - /// `child_pids`. - /// - /// # Arguments - /// - /// * `pid` - An Pid struct representing the process ID. - /// * `child_pids` - A mutable reference to a `Vec` where the child PIDs will be stored. - fn collect_child_pids(pid: Pid, child_pids: &mut Vec) -> Result<(), Error> { - let processes = procfs::process::all_processes() - .map_err(|e| std::io::Error::new(std::io::ErrorKind::Other, e))?; - - for p in processes { - let process = p.map_err(|e| std::io::Error::new(std::io::ErrorKind::Other, e))?; - - let stat = process - .stat() - .map_err(|e| std::io::Error::new(std::io::ErrorKind::Other, e))?; - if stat.ppid == pid.as_raw() { - let pid = Pid::from_raw(process.pid); - child_pids.push(pid); - Self::collect_child_pids(pid, child_pids)?; - } - } - - Ok(()) - } -} - -impl Killable for NativeProcess { - /// Entry point to kill the linux native process. - /// - /// # Arguments - /// - /// * `signal` - A enum value representing the signal type. - fn kill(&self, signal: KillPortSignalOptions) -> Result { - if let Err(err) = Self::kill_process_and_children(self.pid, signal) { - return Err(err); - } - - Ok(true) - } - - /// Returns the type of the killable target. - /// - /// This method is used to identify the type of the target (either a native process or a Docker container) - /// that is being handled. This information can be useful for logging, error handling, or other needs - /// where type of the target is relevant. - /// - /// # Returns - /// - /// * `String` - A string that describes the type of the killable target. For a `NativeProcess` it will return "process", - /// and for a `DockerContainer` it will return "container". - fn get_type(&self) -> String { - "process".to_string() - } -} - -#[derive(Debug)] -struct DockerContainer { - /// Container name. - name: String, -} - -impl DockerContainer { - /// Kill the docker container. - /// - /// # Arguments - /// - /// * `name` - A container name. - /// * `signal` - A enum value representing the signal type. - fn kill_container(name: &String, signal: KillPortSignalOptions) -> Result<(), Error> { - info!("Killing container with name {}", name); - - let rt = Runtime::new()?; - rt.block_on(async { - let docker = Docker::connect_with_socket_defaults() - .map_err(|e| std::io::Error::new(std::io::ErrorKind::Other, e))?; - - let options = KillContainerOptions { - signal: match signal { - KillPortSignalOptions::SIGKILL => "SIGKILL", - KillPortSignalOptions::SIGTERM => "SIGTERM", - }, - }; - - docker - .kill_container(name.replace("/", "").as_str(), Some(options)) - .await - .map_err(|e| std::io::Error::new(std::io::ErrorKind::Other, e)) - }) - } -} - -impl Killable for DockerContainer { - /// Entry point to kill the docker containers. - /// - /// # Arguments - /// - /// * `signal` - A enum value representing the signal type. - fn kill(&self, signal: KillPortSignalOptions) -> Result { - if let Err(err) = Self::kill_container(&self.name, signal) { - return Err(err); - } - - Ok(true) - } - - /// Returns the type of the killable target. - /// - /// This method is used to identify the type of the target (either a native process or a Docker container) - /// that is being handled. This information can be useful for logging, error handling, or other needs - /// where type of the target is relevant. - /// - /// # Returns - /// - /// * `String` - A string that describes the type of the killable target. For a `NativeProcess` it will return "process", - /// and for a `DockerContainer` it will return "container". - fn get_type(&self) -> String { - "container".to_string() - } -} - -/// Attempts to kill processes listening on the specified `port`. -/// -/// # Arguments -/// -/// * `port` - A u16 value representing the port number. -/// * `signal` - A enum value representing the signal type. -/// -/// # Returns -/// -/// A `Result` containing a tuple. The first element is a boolean indicating if -/// at least one process was killed (true if yes, false otherwise). The second -/// element is a string indicating the type of the killed entity. An `Error` is -/// returned if the operation failed or the platform is unsupported. -pub fn kill_processes_by_port( - port: u16, - signal: Signal, -) -> Result<(bool, String), Error> { - let mut killed_any = false; - let mut killable_type = String::new(); - let target_killables = find_target_killables(port)?; - - for killable in target_killables { - killed_any |= killable.kill(signal)?; - killable_type = killable.get_type(); - } - - if !killed_any { - return Err(std::io::Error::new( - io::ErrorKind::Other, - "Unable to kill the process. The process might be running as another user or root. Try again with sudo", - )); - } - - Ok((killed_any, killable_type)) -} - -/// Finds the killables (native processes and docker containers) associated with the specified `port`. -/// -/// Returns a `Vec` of killables. -/// -/// # Arguments -/// -/// * `port` - A u16 value representing the port number. -fn find_target_killables(port: u16) -> Result>, Error> { - let mut target_killables: Vec> = vec![]; - - let target_inodes = find_target_inodes(port); - let target_processes = find_target_processes(target_inodes)?; - for process in target_processes { - target_killables.push(Box::new(process)); - } - - let target_containers = find_target_containers(port)?; - for container in target_containers { - target_killables.push(Box::new(container)); - } - - Ok(target_killables) -} /// Finds the inodes associated with the specified `port`. /// @@ -310,8 +75,9 @@ fn find_target_inodes(port: u16) -> Vec { /// # Arguments /// /// * `inodes` - Target inodes -fn find_target_processes(inodes: Vec) -> Result, Error> { +pub fn find_target_processes(port: u16) -> Result, Error> { let mut target_pids: Vec = vec![]; + let inodes = find_target_inodes(port); for inode in inodes { let processes = procfs::process::all_processes() @@ -325,9 +91,14 @@ fn find_target_processes(inodes: Vec) -> Result, Error> if let FDTarget::Socket(sock_inode) = fd.target { if inode == sock_inode { - debug!("Found process with PID {}", process.pid); + let name = process + .cmdline() + .map_err(|e| std::io::Error::new(std::io::ErrorKind::Other, e))? + .join(" "); + debug!("Found process '{}' with PID {}", name, process.pid()); target_pids.push(NativeProcess { pid: Pid::from_raw(process.pid), + name: name, }); } } @@ -338,65 +109,3 @@ fn find_target_processes(inodes: Vec) -> Result, Error> Ok(target_pids) } - -/// Finds the docker containers associated with the specified `port`. -/// -/// Returns a `Vec` of docker containers. -/// -/// # Arguments -/// -/// * `port` - A u16 value representing the port number. -fn find_target_containers(port: u16) -> Result, Error> { - let mut target_containers: Vec = vec![]; - - let rt = Runtime::new()?; - rt.block_on(async { - let docker = Docker::connect_with_socket_defaults() - .map_err(|e| std::io::Error::new(std::io::ErrorKind::Other, e))?; - - let mut filters = HashMap::new(); - filters.insert("publish".to_string(), vec![port.to_string()]); - filters.insert("status".to_string(), vec!["running".to_string()]); - let options = ListContainersOptions { - filters, - ..Default::default() - }; - - let containers = docker - .list_containers::(Some(options)) - .await - .map_err(|e| std::io::Error::new(std::io::ErrorKind::Other, e))?; - - for container in containers { - let ports = container.ports.clone().unwrap_or_else(|| vec![]); - - for p in ports { - if p.public_port.is_none() { - continue; - }; - - let mut container_names = match container.names.clone() { - Some(container_names) => container_names, - None => continue, - }; - - let container_name = match container_names.pop() { - Some(container_name) => container_name, - None => continue, - }; - - target_containers.push(DockerContainer { - name: container_name.to_string(), - }); - - // Break immediately when we added a container bound to target port, - // because the ports vec has both of IPv4 and IPv6 port mapping information about a same container. - break; - } - } - - Ok::<_, Error>(()) - })?; - - Ok(target_containers) -} diff --git a/src/macos.rs b/src/macos.rs index 896a6f4..bdcbd1a 100644 --- a/src/macos.rs +++ b/src/macos.rs @@ -1,116 +1,76 @@ +use crate::killport::NativeProcess; + use libproc::libproc::file_info::pidfdinfo; use libproc::libproc::file_info::{ListFDs, ProcFDType}; use libproc::libproc::net_info::{SocketFDInfo, SocketInfoKind}; -use libproc::libproc::proc_pid::{listpidinfo, pidinfo}; -use libproc::libproc::task_info::TaskAllInfo; +use libproc::libproc::proc_pid::{listpidinfo, name}; use libproc::processes::{pids_by_type, ProcFilter}; -use log::{debug, info, warn}; -use nix::sys::signal::{self, Signal}; +use log::debug; use nix::unistd::Pid; -use std::ffi::CStr; use std::io; -/// Collect information about all processes. +/// Finds the processes associated with the specified `port`. /// -/// # Returns -/// -/// A vector containing the information of all processes. -fn collect_proc() -> Vec { - let mut base_procs = Vec::new(); - - if let Ok(procs) = pids_by_type(ProcFilter::All) { - for p in procs { - if let Ok(task) = pidinfo::(p as i32, 0) { - base_procs.push(task); - } - } - } - - base_procs -} - -/// Kill processes listening on the specified port. +/// Returns a `Vec` of native processes. /// /// # Arguments /// -/// * `port` - The port number to kill processes listening on. -/// * `signal` - A enum value representing the signal type. -/// -/// # Returns -/// -/// A `Result` containing a tuple. The first element is a boolean indicating if -/// at least one process was killed (true if yes, false otherwise). The second -/// element is a string indicating the type of the killed entity. -pub fn kill_processes_by_port( - port: u16, - signal: Signal, -) -> Result<(bool, String), io::Error> { - let process_infos = collect_proc(); - let mut killed = false; - let killable_type = String::from("process"); // assuming all are Processes for now +/// * `port` - Target port number +pub fn find_target_processes(port: u16) -> Result, io::Error> { + let mut target_pids: Vec = vec![]; - for task in process_infos { - let pid = task.pbsd.pbi_pid as i32; - let mut kill_process = false; - - let fds = listpidinfo::(pid, task.pbsd.pbi_nfiles as usize); - if let Ok(fds) = fds { - for fd in fds { - if let ProcFDType::Socket = fd.proc_fdtype.into() { - if let Ok(socket) = pidfdinfo::(pid, fd.proc_fd) { - match socket.psi.soi_kind.into() { - SocketInfoKind::In => { - if socket.psi.soi_protocol == libc::IPPROTO_UDP { - let info = unsafe { socket.psi.soi_proto.pri_in }; - let local_port = u16::from_be(info.insi_lport as u16); - if local_port == port { - kill_process = true; - break; + if let Ok(procs) = pids_by_type(ProcFilter::All) { + for p in procs { + let pid = p as i32; + let fds = listpidinfo::(pid, 1024); // Large enough to cover typical number of open files + if let Ok(fds) = fds { + for fd in fds { + if let ProcFDType::Socket = fd.proc_fdtype.into() { + if let Ok(socket) = pidfdinfo::(pid, fd.proc_fd) { + // Correctly cast soi_kind to SocketInfoKind + if let Ok(socket_kind) = SocketInfoKind::try_from(socket.psi.soi_kind) { + match socket_kind { + SocketInfoKind::In | SocketInfoKind::Tcp => { + let local_port = unsafe { + match socket_kind { + SocketInfoKind::In => { + socket.psi.soi_proto.pri_in.insi_lport as u16 + } + SocketInfoKind::Tcp => { + socket + .psi + .soi_proto + .pri_tcp + .tcpsi_ini + .insi_lport + as u16 + } + _ => continue, + } + }; + if u16::from_be(local_port) == port { + let process_name = name(pid).map_err(|e| { + io::Error::new(io::ErrorKind::Other, e) + })?; + debug!( + "Found process '{}' with PID {} listening on port {}", + process_name, pid, port + ); + target_pids.push(NativeProcess { + pid: Pid::from_raw(pid), + name: process_name, + }); + } } + _ => (), } } - SocketInfoKind::Tcp => { - let info = unsafe { socket.psi.soi_proto.pri_tcp }; - let local_port = u16::from_be(info.tcpsi_ini.insi_lport as u16); - if local_port == port { - kill_process = true; - break; - } - } - _ => (), } } } } } - - if kill_process { - debug!("Found process with PID {}", pid); - let pid = Pid::from_raw(pid); - let cmd = unsafe { - CStr::from_ptr(task.pbsd.pbi_comm.as_ptr()) - .to_string_lossy() - .into_owned() - }; - - if cmd.starts_with("com.docker") { - warn!("Warning: Found Docker. You might need to stop the container manually."); - } else { - info!("Killing process with PID {}", pid); - match signal::kill(pid, signal) { - Ok(_) => { - killed = true; - } - Err(e) => { - return Err(io::Error::new( - io::ErrorKind::Other, - format!("Failed to kill process {}: {}", pid, e), - )); - } - } - } - } } - Ok((killed, killable_type)) + Ok(target_pids) } diff --git a/src/main.rs b/src/main.rs index 09e1efb..a4dedc0 100644 --- a/src/main.rs +++ b/src/main.rs @@ -4,70 +4,15 @@ //! The utility accepts a list of port numbers as input and attempts to //! terminate any processes listening on those ports. -#[cfg(target_os = "linux")] -mod linux; -#[cfg(target_os = "macos")] -mod macos; -#[cfg(target_os = "windows")] -mod windows; - -#[cfg(target_os = "linux")] -use linux::kill_processes_by_port; -#[cfg(target_os = "macos")] -use macos::kill_processes_by_port; -#[cfg(target_os = "windows")] -use windows::kill_processes_by_port; - use clap::Parser; -use clap_verbosity_flag::{Verbosity, WarnLevel}; +use clap_verbosity_flag::LevelFilter; use log::error; -use nix::sys::signal::Signal; -use std::{process::exit, str::FromStr}; - -/// `killport` utility. -#[derive(Parser, Debug)] -#[command(author, version, about, long_about = None)] -struct KillPortArgs { - /// A list of port numbers to kill processes on. - #[arg( - name = "ports", - help = "The list of port numbers to kill processes or containers on", - required = true - )] - ports: Vec, +use std::io::Write; +use std::process::exit; - /// An option to specify the type of signal to be sent. - #[arg( - long, - short = 's', - name = "SIG", - help = "SIG is a signal name", - default_value = "sigterm", - value_parser = parse_signal - )] - signal: Signal, +use killport::cli::{service_descriptors, KillPortArgs}; +use killport::killport::{Killport, KillportOperations}; - /// A verbosity flag to control the level of logging output. - #[command(flatten)] - verbose: Verbosity, -} - -fn parse_signal(arg: &str) -> Result { - let str_arg = arg.parse::(); - match str_arg { - Ok(str_arg) => { - let signal_str = str_arg.to_uppercase(); - let signal = Signal::from_str(signal_str.as_str())?; - return Ok(signal); - } - Err(e) => Err(std::io::Error::new(std::io::ErrorKind::Other, e)), - } -} - -/// The `main` function is the entry point of the `killport` utility. -/// -/// It parses command-line arguments, sets up the logging environment, and -/// attempts to kill processes listening on the specified ports. fn main() { // Parse command-line arguments let args = KillPortArgs::parse(); @@ -79,28 +24,50 @@ fn main() { .map(|level| level.to_level_filter()) .unwrap(); - env_logger::Builder::new() + env_logger::builder() + .format(move |buf, record| { + if log_level <= LevelFilter::Info { + writeln!(buf, "{}", record.args()) + } else { + // Default format for lower levels + writeln!( + buf, + "[{}] {}: {}", + record.target(), + record.level(), + record.args() + ) + } + }) .format_module_path(log_level == log::LevelFilter::Trace) .format_target(log_level == log::LevelFilter::Trace) .format_timestamp(Option::None) .filter_level(log_level) .init(); - // Determine a signal to be sent. - // If an option for signal number is added, we can determine a signal to be sent by signal number. - let signal = args.signal; + let (service_type_singular, _service_type_plural) = service_descriptors(args.mode); + + // Create an instance of Killport + let killport = Killport; // Attempt to kill processes listening on specified ports for port in args.ports { - match kill_processes_by_port(port, signal) { - Ok((killed, killable_type)) => { - if killed { - println!( - "Successfully killed {} listening on port {}", - killable_type, port - ); + match killport.kill_service_by_port(port, args.signal, args.mode, args.dry_run) { + Ok(killed_services) => { + if killed_services.is_empty() { + println!("No {} found using port {}", service_type_singular, port); } else { - println!("No services found using port {}", port); + for (killable_type, name) in killed_services { + let action = if args.dry_run { + "Would kill" + } else { + "Successfully killed" + }; + println!( + "{} {} '{}' listening on port {}", + action, killable_type, name, port + ); + } } } Err(err) => { diff --git a/tests/integration_test.rs b/tests/integration_test.rs index 86662fa..6ee506d 100644 --- a/tests/integration_test.rs +++ b/tests/integration_test.rs @@ -1,182 +1,111 @@ +mod utils; +use utils::start_listener_process; + use assert_cmd::Command; -use std::io::Write; -use std::{fs::File, path}; -use std::{thread, time}; use tempfile::tempdir; #[test] -fn test_killport() { - // Create a temporary directory for testing. - let tempdir = tempdir().expect("Failed to create temporary directory"); - let tempdir_path = tempdir.path(); - generate_temp_process(tempdir_path); - - // Test killport execution without options - test_killport_noargs(tempdir_path); - - // Test killport execution with -s option - // Hangup - test_killport_signal_arg(tempdir_path, "sighup"); - // Interrupt - test_killport_signal_arg(tempdir_path, "sigint"); - // Quit - test_killport_signal_arg(tempdir_path, "sigquit"); - // Illegal instruction (not reset when caught) - test_killport_signal_arg(tempdir_path, "sigill"); - // Trace trap (not reset when caught) - test_killport_signal_arg(tempdir_path, "sigtrap"); - // Abort - test_killport_signal_arg(tempdir_path, "sigabrt"); - // Bus error - test_killport_signal_arg(tempdir_path, "sigbus"); - // Floating point exception - test_killport_signal_arg(tempdir_path, "sigfpe"); - // Kill (cannot be caught or ignored) - test_killport_signal_arg(tempdir_path, "sigkill"); - // User defined signal 1 - test_killport_signal_arg(tempdir_path, "sigusr1"); - // Segmentation violation - test_killport_signal_arg(tempdir_path, "sigsegv"); - // User defined signal 2 - test_killport_signal_arg(tempdir_path, "sigusr2"); - // Write on a pipe with no one to read it - test_killport_signal_arg(tempdir_path, "sigpipe"); - // Alarm clock - test_killport_signal_arg(tempdir_path, "sigalrm"); - // Software termination signal from kill - test_killport_signal_arg(tempdir_path, "sigterm"); - // Stack fault (obsolete) - #[cfg(all( - any( - target_os = "android", - target_os = "emscripten", - target_os = "fuchsia", - target_os = "linux" - ), - not(any(target_arch = "mips", target_arch = "mips64", target_arch = "sparc64")) - ))] - test_killport_signal_arg(tempdir_path, "sigstkflt"); - // To parent on child stop or exit - test_killport_signal_arg(tempdir_path, "sigchld"); - // Continue a stopped process - test_killport_signal_arg(tempdir_path, "sigcont"); - // Sendable stop signal not from tty - test_killport_signal_arg(tempdir_path, "sigstop"); - // Stop signal from tty - test_killport_signal_arg(tempdir_path, "sigtstp"); - // To readers pgrp upon background tty read - test_killport_signal_arg(tempdir_path, "sigttin"); - // Like TTIN if (tp->t_local<OSTOP) - test_killport_signal_arg(tempdir_path, "sigttou"); - // Urgent condition on IO channel - test_killport_signal_arg(tempdir_path, "sigurg"); - // Exceeded CPU time limit - test_killport_signal_arg(tempdir_path, "sigxcpu"); - // Exceeded file size limit - test_killport_signal_arg(tempdir_path, "sigxfsz"); - // Virtual time alarm - test_killport_signal_arg(tempdir_path, "sigvtalrm"); - // Profiling time alarm - test_killport_signal_arg(tempdir_path, "sigprof"); - // Window size changes - test_killport_signal_arg(tempdir_path, "sigwinch"); - // Input/output possible signal - #[cfg(not(target_os = "haiku"))] - #[cfg_attr(docsrs, doc(cfg(all())))] - test_killport_signal_arg(tempdir_path, "sigio"); - #[cfg(any( - target_os = "android", - target_os = "emscripten", - target_os = "fuchsia", - target_os = "linux" - ))] - #[cfg_attr(docsrs, doc(cfg(all())))] - // Power failure imminent. - test_killport_signal_arg(tempdir_path, "sigpwr"); - // Bad system call - test_killport_signal_arg(tempdir_path, "sigsys"); - #[cfg(not(any( - target_os = "android", - target_os = "emscripten", - target_os = "fuchsia", - target_os = "linux", - target_os = "redox", - target_os = "haiku" - )))] - #[cfg_attr(docsrs, doc(cfg(all())))] - // Emulator trap - test_killport_signal_arg(tempdir_path, "sigemt"); - #[cfg(not(any( - target_os = "android", - target_os = "emscripten", - target_os = "fuchsia", - target_os = "linux", - target_os = "redox", - target_os = "haiku" - )))] - #[cfg_attr(docsrs, doc(cfg(all())))] - // Information request - test_killport_signal_arg(tempdir_path, "siginfo"); +fn test_basic_kill_no_process() { + let mut cmd = Command::cargo_bin("killport").unwrap(); + cmd.args(&["8080"]) + .assert() + .success() + .stdout("No service found using port 8080\n"); } -fn test_killport_signal_arg(tempdir_path: &path::Path, signal: &str) { - let mut mock_process = std::process::Command::new(tempdir_path.join("mock_process")) - .spawn() - .expect("Failed to run the mock process"); +/// Tests basic functionality of killing a process on a specified port without any additional options. +#[test] +fn test_basic_kill_process() { + let tempdir = tempdir().unwrap(); + let tempdir_path = tempdir.path(); + let mut child = start_listener_process(tempdir_path, 8080); - // Test killport command with specifying a signal name - let mut cmd = Command::cargo_bin("killport").expect("Failed to find killport binary"); - cmd.arg("8080") - .arg("-s") - .arg(signal) + let mut cmd = Command::cargo_bin("killport").unwrap(); + cmd.args(&["8080"]) .assert() .success() - .stdout("Successfully killed process listening on port 8080\n"); + .stdout("Successfully killed process 'mock_process' listening on port 8080\n"); - // Cleanup: Terminate the mock process (if still running). - let _ = mock_process.kill(); + // Clean up + let _ = child.kill(); + let _ = child.wait(); } -fn test_killport_noargs(tempdir_path: &path::Path) { - let mut mock_process = std::process::Command::new(tempdir_path.join("mock_process")) - .spawn() - .expect("Failed to run the mock process"); +/// Tests the `--signal` option with various signals. +#[test] +fn test_signal_handling() { + let tempdir = tempdir().unwrap(); + let tempdir_path = tempdir.path(); + + for signal in ["sighup", "sigint", "sigkill"].iter() { + let mut child = start_listener_process(tempdir_path, 8081); + let mut cmd = Command::cargo_bin("killport").unwrap(); + cmd.args(&["8081", "-s", signal]) + .assert() + .success() + .stdout(format!( + "Successfully killed process 'mock_process' listening on port 8081\n" + )); + + // Clean up + let _ = child.kill(); + let _ = child.wait(); + } +} + +/// Tests the `--mode` option for different operation modes. +#[test] +fn test_mode_option() { + let tempdir = tempdir().unwrap(); + let tempdir_path = tempdir.path(); + + for mode in ["auto", "process"].iter() { + let mut child = start_listener_process(tempdir_path, 8082); + let mut cmd = Command::cargo_bin("killport").unwrap(); + cmd.args(&["8082", "--mode", mode]) + .assert() + .success() + .stdout(format!( + "Successfully killed process 'mock_process' listening on port 8082\n" + )); + // Clean up + let _ = child.kill(); + let _ = child.wait(); + } - // Test killport command - let mut cmd = Command::cargo_bin("killport").expect("Failed to find killport binary"); - cmd.arg("8080") + let mut cmd = Command::cargo_bin("killport").unwrap(); + cmd.args(&["8082", "--mode", "auto"]) .assert() .success() - .stdout("Successfully killed process listening on port 8080\n"); + .stdout(format!("No service found using port 8082\n")); - // Cleanup: Terminate the mock process (if still running). - let _ = mock_process.kill(); + let mut cmd = Command::cargo_bin("killport").unwrap(); + cmd.args(&["8082", "--mode", "process"]) + .assert() + .success() + .stdout(format!("No process found using port 8082\n")); + + let mut cmd = Command::cargo_bin("killport").unwrap(); + cmd.args(&["8082", "--mode", "container"]) + .assert() + .success() + .stdout(format!("No container found using port 8082\n")); } -fn generate_temp_process(tempdir_path: &path::Path) { - // Create a mock process that listens on a port. - let mock_process = format!( - r#" - use std::net::TcpListener; - fn main() {{ - let _listener = TcpListener::bind("127.0.0.1:8080").unwrap(); - loop {{}} - }} - "# - ); - - let mock_process_path = tempdir_path.join("mock_process.rs"); - let mut file = File::create(&mock_process_path).expect("Failed to create mock_process.rs file"); - file.write_all(mock_process.as_bytes()) - .expect("Failed to write mock_process.rs content"); - - // Compile and run the mock process in the background. - let status = std::process::Command::new("rustc") - .arg(&mock_process_path) - .arg("--out-dir") - .arg(&tempdir_path) - .status() - .expect("Failed to compile mock_process.rs"); - - assert!(status.success(), "Mock process compilation failed"); +/// Tests the `--dry-run` option to ensure no actual killing of the process. +#[test] +fn test_dry_run_option() { + let tempdir = tempdir().unwrap(); + let tempdir_path = tempdir.path(); + let mut child = start_listener_process(tempdir_path, 8083); + + let mut cmd = Command::cargo_bin("killport").unwrap(); + cmd.args(&["8083", "--dry-run"]) + .assert() + .success() + .stdout("Would kill process 'mock_process' listening on port 8083\n"); + + // Clean up + let _ = child.kill(); + let _ = child.wait(); } diff --git a/tests/killport_tests.rs b/tests/killport_tests.rs new file mode 100644 index 0000000..d668e80 --- /dev/null +++ b/tests/killport_tests.rs @@ -0,0 +1,141 @@ +use killport::cli::Mode; +use killport::docker::DockerContainer; +use killport::killport::KillportOperations; +use killport::killport::{Killable, NativeProcess}; +use mockall::*; +use nix::sys::signal::Signal; +use nix::unistd::Pid; +use std::io::Error; +use std::sync::{Arc, Mutex}; + +// Setup Mocks +mock! { + DockerContainer {} + + impl Killable for DockerContainer { + fn kill(&self, signal: Signal) -> Result; + fn get_type(&self) -> String; + fn get_name(&self) -> String; + } +} +mock! { + NativeProcess {} + + impl Killable for NativeProcess { + fn kill(&self, signal: Signal) -> Result; + fn get_type(&self) -> String; + fn get_name(&self) -> String; + } +} +mock! { + KillportOperations { + fn find_target_killables(&self, port: u16, mode: Mode) -> Result>, Error>; + fn kill_service_by_port(&self, port: u16, signal: Signal, mode: Mode, dry_run: bool) -> Result, Error>; + } +} + +#[test] +fn native_process_kill_succeeds() { + let mut mock_process = MockNativeProcess::new(); + // Setup the expectation for the mock + mock_process + .expect_kill() + .with(mockall::predicate::eq(Signal::SIGKILL)) + .times(1) // Ensure the kill method is called exactly once + .returning(|_| Ok(true)); // Simulate successful kill + + assert_eq!(mock_process.kill(Signal::SIGKILL).unwrap(), true); +} + +#[test] +fn docker_container_kill_succeeds() { + let mut mock_container = MockDockerContainer::new(); + mock_container + .expect_kill() + .with(mockall::predicate::eq(Signal::SIGKILL)) + .times(1) + .returning(|_| Ok(true)); + + assert_eq!(mock_container.kill(Signal::SIGKILL).unwrap(), true); +} + +#[test] +fn find_killables_processes_only() { + let mut mock_killport = MockKillportOperations::new(); + + mock_killport + .expect_find_target_killables() + .withf(|&port, &mode| port == 8080 && mode == Mode::Process) + .returning(|_, _| { + let mut mock_process = MockNativeProcess::new(); + mock_process + .expect_get_type() + .return_const("process".to_string()); + mock_process + .expect_get_name() + .return_const("mock_process".to_string()); + Ok(vec![Box::new(mock_process)]) + }); + + let port = 8080; + let mode = Mode::Process; + let found_killables = mock_killport.find_target_killables(port, mode).unwrap(); + assert!(found_killables.iter().all(|k| k.get_type() == "process")); +} + +#[test] +fn kill_service_by_port_dry_run() { + let mut mock_killport = MockKillportOperations::new(); + let mut mock_process = MockNativeProcess::new(); + + mock_process.expect_kill().never(); + mock_process + .expect_get_type() + .return_const("process".to_string()); + mock_process + .expect_get_name() + .return_const("mock_process".to_string()); + + mock_killport + .expect_kill_service_by_port() + .returning(|_, _, _, _| Ok(vec![("process".to_string(), "mock_process".to_string())])); + + let port = 8080; + let mode = Mode::Process; + let dry_run = true; + let signal = Signal::SIGKILL; + + let results = mock_killport + .kill_service_by_port(port, signal, mode, dry_run) + .unwrap(); + assert_eq!(results.len(), 1); + assert_eq!(results[0].0, "process"); + assert_eq!(results[0].1, "mock_process"); +} + +#[test] +fn check_process_type_and_name() { + let process = NativeProcess { + pid: Pid::from_raw(1234), + name: "unique_process".to_string(), + }; + + assert_eq!(process.get_type(), "process"); + assert_eq!(process.get_name(), "unique_process"); +} + +#[test] +fn check_docker_container_type_and_name() { + let mut mock_container = MockDockerContainer::new(); + mock_container + .expect_get_type() + .times(1) + .returning(|| "container".to_string()); + mock_container + .expect_get_name() + .times(1) + .returning(|| "docker_container".to_string()); + + assert_eq!(mock_container.get_type(), "container"); + assert_eq!(mock_container.get_name(), "docker_container"); +} diff --git a/tests/utils.rs b/tests/utils.rs new file mode 100644 index 0000000..7feb689 --- /dev/null +++ b/tests/utils.rs @@ -0,0 +1,55 @@ +use std::process::{Child, Command as SystemCommand}; +use std::{fs::File, io::Write, path::Path, thread, time::Duration}; + +/// Generates and starts a mock Rust application that listens on a given port. +pub fn start_listener_process(tempdir_path: &Path, port: u16) -> Child { + let mock_process_code = format!( + r#" + use std::net::TcpListener; + use std::time::Duration; + use std::thread; + + fn main() {{ + let mut listener = None; + for _ in 0..5 {{ + match TcpListener::bind("127.0.0.1:{}") {{ + Ok(l) => {{ + listener = Some(l); + break; + }}, + Err(_) => thread::sleep(Duration::from_millis(500)), + }} + }} + let listener = listener.expect("Failed to bind to port after several attempts"); + println!("Listening on port {}"); + loop {{ let _ = listener.accept(); }} + }} + "#, + port, port + ); + + let mock_process_path = tempdir_path.join("mock_process.rs"); + let mut file = File::create(&mock_process_path).expect("Failed to create mock_process.rs file"); + file.write_all(mock_process_code.as_bytes()) + .expect("Failed to write mock process code"); + + let status = SystemCommand::new("rustc") + .args(&[ + mock_process_path.to_str().unwrap(), + "--out-dir", + tempdir_path.to_str().unwrap(), + ]) + .status() + .expect("Failed to compile the mock process"); + + assert!(status.success(), "Compilation of mock process failed"); + + let mock_binary_path = tempdir_path.join("mock_process"); + let child = SystemCommand::new(mock_binary_path) + .spawn() + .expect("Failed to start the mock process"); + + thread::sleep(Duration::from_secs(1)); + + child +}