diff --git a/Cargo.lock b/Cargo.lock index 6a930c5..75996e2 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3,349 +3,129 @@ version = 3 [[package]] -name = "actix-codec" -version = "0.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f7b0a21988c1bf877cf4759ef5ddaac04c1c9fe808c9142ecb78ba97d97a28a" -dependencies = [ - "bitflags", - "bytes", - "futures-core", - "futures-sink", - "memchr", - "pin-project-lite", - "tokio", - "tokio-util", - "tracing", -] - -[[package]] -name = "actix-files" -version = "0.6.6" +name = "addr2line" +version = "0.24.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0773d59061dedb49a8aed04c67291b9d8cf2fe0b60130a381aab53c6dd86e9be" +checksum = "dfbe277e56a376000877090da837660b4427aad530e3028d44e0bffe4f89a1c1" dependencies = [ - "actix-http", - "actix-service", - "actix-utils", - "actix-web", - "bitflags", - "bytes", - "derive_more", - "futures-core", - "http-range", - "log", - "mime", - "mime_guess", - "percent-encoding", - "pin-project-lite", - "v_htmlescape", + "gimli", ] [[package]] -name = "actix-http" -version = "3.9.0" +name = "adler2" +version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d48f96fc3003717aeb9856ca3d02a8c7de502667ad76eeacd830b48d2e91fac4" -dependencies = [ - "actix-codec", - "actix-rt", - "actix-service", - "actix-utils", - "ahash", - "base64", - "bitflags", - "brotli", - "bytes", - "bytestring", - "derive_more", - "encoding_rs", - "flate2", - "futures-core", - "h2 0.3.26", - "http 0.2.12", - "httparse", - "httpdate", - "itoa", - "language-tags", - "local-channel", - "mime", - "percent-encoding", - "pin-project-lite", - "rand", - "sha1", - "smallvec", - "tokio", - "tokio-util", - "tracing", - "zstd", -] +checksum = "512761e0bb2578dd7380c6baaa0f4ce03e84f95e960231d1dec8bf4d7d6e2627" [[package]] -name = "actix-macros" -version = "0.2.4" +name = "anyhow" +version = "1.0.93" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e01ed3140b2f8d422c68afa1ed2e85d996ea619c988ac834d255db32138655cb" -dependencies = [ - "quote", - "syn", -] +checksum = "4c95c10ba0b00a02636238b814946408b1322d5ac4760326e6fb8ec956d85775" [[package]] -name = "actix-router" +name = "argon2" version = "0.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "13d324164c51f63867b57e73ba5936ea151b8a41a1d23d1031eeb9f70d0236f8" -dependencies = [ - "bytestring", - "cfg-if", - "http 0.2.12", - "regex", - "regex-lite", - "serde", - "tracing", -] - -[[package]] -name = "actix-rt" -version = "2.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "24eda4e2a6e042aa4e55ac438a2ae052d3b5da0ecf83d7411e1a368946925208" +checksum = "3c3610892ee6e0cbce8ae2700349fcf8f98adb0dbfbee85aec3c9179d29cc072" dependencies = [ - "futures-core", - "tokio", + "base64ct", + "blake2", + "cpufeatures", + "password-hash", ] [[package]] -name = "actix-server" -version = "2.5.0" +name = "async-trait" +version = "0.1.83" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ca2549781d8dd6d75c40cf6b6051260a2cc2f3c62343d761a969a0640646894" +checksum = "721cae7de5c34fbb2acd27e21e6d2cf7b886dce0c27388d46c4e6c47ea4318dd" dependencies = [ - "actix-rt", - "actix-service", - "actix-utils", - "futures-core", - "futures-util", - "mio", - "socket2", - "tokio", - "tracing", + "proc-macro2", + "quote", + "syn", ] [[package]] -name = "actix-service" -version = "2.0.2" +name = "atomic-waker" +version = "1.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b894941f818cfdc7ccc4b9e60fa7e53b5042a2e8567270f9147d5591893373a" -dependencies = [ - "futures-core", - "paste", - "pin-project-lite", -] +checksum = "1505bd5d3d116872e7271a6d4e16d81d0c8570876c8de68093a09ac269d8aac0" [[package]] -name = "actix-utils" -version = "3.0.1" +name = "autocfg" +version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "88a1dcdff1466e3c2488e1cb5c36a71822750ad43839937f85d2f4d9f8b705d8" -dependencies = [ - "local-waker", - "pin-project-lite", -] +checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26" [[package]] -name = "actix-web" -version = "4.9.0" +name = "axum" +version = "0.7.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9180d76e5cc7ccbc4d60a506f2c727730b154010262df5b910eb17dbe4b8cb38" +checksum = "504e3947307ac8326a5437504c517c4b56716c9d98fac0028c2acc7ca47d70ae" dependencies = [ - "actix-codec", - "actix-http", - "actix-macros", - "actix-router", - "actix-rt", - "actix-server", - "actix-service", - "actix-utils", - "actix-web-codegen", - "ahash", + "async-trait", + "axum-core", "bytes", - "bytestring", - "cfg-if", - "cookie", - "derive_more", - "encoding_rs", - "futures-core", "futures-util", - "impl-more", + "http", + "http-body", + "http-body-util", + "hyper", + "hyper-util", "itoa", - "language-tags", - "log", + "matchit", + "memchr", "mime", - "once_cell", + "percent-encoding", "pin-project-lite", - "regex", - "regex-lite", + "rustversion", "serde", "serde_json", + "serde_path_to_error", "serde_urlencoded", - "smallvec", - "socket2", - "time", - "url", -] - -[[package]] -name = "actix-web-codegen" -version = "4.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f591380e2e68490b5dfaf1dd1aa0ebe78d84ba7067078512b4ea6e4492d622b8" -dependencies = [ - "actix-router", - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "addr2line" -version = "0.22.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e4503c46a5c0c7844e948c9a4d6acd9f50cccb4de1c48eb9e291ea17470c678" -dependencies = [ - "gimli", -] - -[[package]] -name = "adler" -version = "1.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" - -[[package]] -name = "adler2" -version = "2.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "512761e0bb2578dd7380c6baaa0f4ce03e84f95e960231d1dec8bf4d7d6e2627" - -[[package]] -name = "ahash" -version = "0.8.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e89da841a80418a9b391ebaea17f5c112ffaaa96f621d2c285b5174da76b9011" -dependencies = [ - "cfg-if", - "getrandom", - "once_cell", - "version_check", - "zerocopy", -] - -[[package]] -name = "aho-corasick" -version = "1.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916" -dependencies = [ - "memchr", -] - -[[package]] -name = "alloc-no-stdlib" -version = "2.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cc7bb162ec39d46ab1ca8c77bf72e890535becd1751bb45f64c597edb4c8c6b3" - -[[package]] -name = "alloc-stdlib" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "94fb8275041c72129eb51b7d0322c29b8387a0386127718b096429201a5d6ece" -dependencies = [ - "alloc-no-stdlib", -] - -[[package]] -name = "anstream" -version = "0.6.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "64e15c1ab1f89faffbf04a634d5e1962e9074f2741eef6d97f3c4e322426d526" -dependencies = [ - "anstyle", - "anstyle-parse", - "anstyle-query", - "anstyle-wincon", - "colorchoice", - "is_terminal_polyfill", - "utf8parse", -] - -[[package]] -name = "anstyle" -version = "1.0.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1bec1de6f59aedf83baf9ff929c98f2ad654b97c9510f4e70cf6f661d49fd5b1" - -[[package]] -name = "anstyle-parse" -version = "0.2.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eb47de1e80c2b463c735db5b217a0ddc39d612e7ac9e2e96a5aed1f57616c1cb" -dependencies = [ - "utf8parse", -] - -[[package]] -name = "anstyle-query" -version = "1.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d36fc52c7f6c869915e99412912f22093507da8d9e942ceaf66fe4b7c14422a" -dependencies = [ - "windows-sys 0.52.0", + "sync_wrapper 1.0.1", + "tokio", + "tower", + "tower-layer", + "tower-service", + "tracing", ] [[package]] -name = "anstyle-wincon" -version = "3.0.4" +name = "axum-core" +version = "0.4.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5bf74e1b6e971609db8ca7a9ce79fd5768ab6ae46441c572e46cf596f59e57f8" +checksum = "09f2bd6146b97ae3359fa0cc6d6b376d9539582c7b4220f041a33ec24c226199" dependencies = [ - "anstyle", - "windows-sys 0.52.0", + "async-trait", + "bytes", + "futures-util", + "http", + "http-body", + "http-body-util", + "mime", + "pin-project-lite", + "rustversion", + "sync_wrapper 1.0.1", + "tower-layer", + "tower-service", + "tracing", ] -[[package]] -name = "anyhow" -version = "1.0.87" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "10f00e1f6e58a40e807377c75c6a7f97bf9044fab57816f2414e6f5f4499d7b8" - -[[package]] -name = "atomic-waker" -version = "1.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1505bd5d3d116872e7271a6d4e16d81d0c8570876c8de68093a09ac269d8aac0" - -[[package]] -name = "autocfg" -version = "1.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c4b4d0bd25bd0b74681c0ad21497610ce1b7c91b1022cd21c80c6fbdd9476b0" - [[package]] name = "backtrace" -version = "0.3.73" +version = "0.3.74" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5cc23269a4f8976d0a4d2e7109211a419fe30e8d88d677cd60b6bc79c5732e0a" +checksum = "8d82cb332cdfaed17ae235a638438ac4d4839913cc2af585c3c6746e8f8bee1a" dependencies = [ "addr2line", - "cc", "cfg-if", "libc", - "miniz_oxide 0.7.4", + "miniz_oxide", "object", "rustc-demangle", + "windows-targets", ] [[package]] @@ -354,19 +134,32 @@ version = "0.22.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" +[[package]] +name = "base64ct" +version = "1.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8c3c1a368f70d6cf7302d78f8f7093da241fb8e8807c05cc9e51a125895a6d5b" + [[package]] name = "bitflags" version = "2.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de" +[[package]] +name = "blake2" +version = "0.10.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "46502ad458c9a52b69d4d4d32775c788b7a1b85e8bc9d482d92250fc0e3f8efe" +dependencies = [ + "digest", +] + [[package]] name = "blimp" version = "0.1.0" dependencies = [ - "anyhow", "common", - "tokio", ] [[package]] @@ -385,12 +178,12 @@ dependencies = [ name = "blimp-server" version = "0.1.0" dependencies = [ - "actix-files", - "actix-web", + "axum", "common", - "env_logger", + "envy", "serde", - "serde_json", + "tracing", + "tracing-subscriber", ] [[package]] @@ -402,27 +195,6 @@ dependencies = [ "generic-array", ] -[[package]] -name = "brotli" -version = "6.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74f7971dbd9326d58187408ab83117d8ac1bb9c17b085fdacd1cf2f598719b6b" -dependencies = [ - "alloc-no-stdlib", - "alloc-stdlib", - "brotli-decompressor", -] - -[[package]] -name = "brotli-decompressor" -version = "4.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a45bd2e4095a8b518033b128020dd4a55aab1c0a381ba4404a472630f4bc362" -dependencies = [ - "alloc-no-stdlib", - "alloc-stdlib", -] - [[package]] name = "bumpalo" version = "3.16.0" @@ -437,18 +209,9 @@ checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" [[package]] name = "bytes" -version = "1.7.1" +version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8318a53db07bb3f8dca91a600466bdb3f2eaadeedfdbcf02e1accbad9271ba50" - -[[package]] -name = "bytestring" -version = "1.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74d80203ea6b29df88012294f62733de21cfeab47f17b41af3a38bc30a03ee72" -dependencies = [ - "bytes", -] +checksum = "9ac0150caa2ae65ca5bd83f25c7de183dea78d4d366469f148435e2acfbad0da" [[package]] name = "bzip2" @@ -473,12 +236,10 @@ dependencies = [ [[package]] name = "cc" -version = "1.1.18" +version = "1.1.37" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b62ac837cdb5cb22e10a256099b4fc502b1dfe560cb282963a974d7abd80e476" +checksum = "40545c26d092346d8a8dab71ee48e7685a7a9cba76e634790c215b41a4a7b4cf" dependencies = [ - "jobserver", - "libc", "shlex", ] @@ -499,12 +260,6 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" -[[package]] -name = "colorchoice" -version = "1.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d3fd119d74b830634cea2a0f58bbd0d54540518a14397557951e79340abc28c0" - [[package]] name = "common" version = "0.1.0" @@ -522,26 +277,11 @@ dependencies = [ "serde_json", "tar", "tokio", + "tokio-util", + "utils", "xz2", ] -[[package]] -name = "convert_case" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6245d59a3e82a7fc217c5828a6692dbc6dfb63a0c8c90495621f7b9d79704a0e" - -[[package]] -name = "cookie" -version = "0.16.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e859cd57d0710d9e06c381b550c06e76992472a8c6d527aecd2fc673dcc231fb" -dependencies = [ - "percent-encoding", - "time", - "version_check", -] - [[package]] name = "core-foundation" version = "0.9.4" @@ -586,28 +326,6 @@ dependencies = [ "typenum", ] -[[package]] -name = "deranged" -version = "0.3.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b42b6fa04a440b495c8b04d0e71b707c585f83cb9cb28cf8cd0d976c315e31b4" -dependencies = [ - "powerfmt", -] - -[[package]] -name = "derive_more" -version = "0.99.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f33878137e4dafd7fa914ad4e259e18a4e8e532b9617a2d0150262bf53abfce" -dependencies = [ - "convert_case", - "proc-macro2", - "quote", - "rustc_version", - "syn", -] - [[package]] name = "digest" version = "0.10.7" @@ -616,38 +334,36 @@ checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" dependencies = [ "block-buffer", "crypto-common", + "subtle", ] [[package]] -name = "encoding_rs" -version = "0.8.34" +name = "displaydoc" +version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b45de904aa0b010bce2ab45264d0631681847fa7b6f2eaa7dab7619943bc4f59" +checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0" dependencies = [ - "cfg-if", + "proc-macro2", + "quote", + "syn", ] [[package]] -name = "env_filter" -version = "0.1.2" +name = "encoding_rs" +version = "0.8.35" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4f2c92ceda6ceec50f43169f9ee8424fe2db276791afde7b2cd8bc084cb376ab" +checksum = "75030f3c4f45dafd7586dd6780965a8c7e8e285a5ecb86713e63a79c5b2766f3" dependencies = [ - "log", - "regex", + "cfg-if", ] [[package]] -name = "env_logger" -version = "0.11.5" +name = "envy" +version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e13fa619b91fb2381732789fc5de83b45675e882f66623b7d8cb4f643017018d" +checksum = "3f47e0157f2cb54f5ae1bd371b30a2ae4311e1c028f575cd4e81de7353215965" dependencies = [ - "anstream", - "anstyle", - "env_filter", - "humantime", - "log", + "serde", ] [[package]] @@ -668,9 +384,9 @@ dependencies = [ [[package]] name = "fastrand" -version = "2.1.1" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e8c02a5121d4ea3eb16a80748c74f5549a5665e4c21333c6098f283870fbdea6" +checksum = "486f806e73c5707928240ddc295403b1b93c96a02038563881c4a2fd84b81ac4" [[package]] name = "filetime" @@ -686,12 +402,12 @@ dependencies = [ [[package]] name = "flate2" -version = "1.0.33" +version = "1.0.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "324a1be68054ef05ad64b861cc9eaf1d623d2d8cb25b4bf2cb9cdd902b4bf253" +checksum = "a1b589b4dc103969ad3cf85c950899926ec64300a1a46d76c03a6072957036f0" dependencies = [ "crc32fast", - "miniz_oxide 0.8.0", + "miniz_oxide", ] [[package]] @@ -726,9 +442,9 @@ dependencies = [ [[package]] name = "futures" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "645c6916888f6cb6350d2550b80fb63e734897a8498abe35cfb732b6487804b0" +checksum = "65bc07b1a8bc7c85c5f2e110c476c7389b4554ba72af57d8445ea63a576b0876" dependencies = [ "futures-channel", "futures-core", @@ -741,9 +457,9 @@ dependencies = [ [[package]] name = "futures-channel" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eac8f7d7865dcb88bd4373ab671c8cf4508703796caa2b1985a9ca867b3fcb78" +checksum = "2dff15bf788c671c1934e366d07e30c1814a8ef514e1af724a602e8a2fbe1b10" dependencies = [ "futures-core", "futures-sink", @@ -751,15 +467,15 @@ dependencies = [ [[package]] name = "futures-core" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dfc6580bb841c5a68e9ef15c77ccc837b40a7504914d52e47b8b0e9bbda25a1d" +checksum = "05f29059c0c2090612e8d742178b0580d2dc940c837851ad723096f87af6663e" [[package]] name = "futures-executor" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a576fc72ae164fca6b9db127eaa9a9dda0d61316034f33a0a0d4eda41f02b01d" +checksum = "1e28d1d997f585e54aebc3f97d39e72338912123a67330d723fdbb564d646c9f" dependencies = [ "futures-core", "futures-task", @@ -768,15 +484,15 @@ dependencies = [ [[package]] name = "futures-io" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a44623e20b9681a318efdd71c299b6b222ed6f231972bfe2f224ebad6311f0c1" +checksum = "9e5c1b78ca4aae1ac06c48a526a655760685149f0d465d21f37abfe57ce075c6" [[package]] name = "futures-macro" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac" +checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650" dependencies = [ "proc-macro2", "quote", @@ -785,21 +501,21 @@ dependencies = [ [[package]] name = "futures-sink" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9fb8e00e87438d937621c1c6269e53f536c14d3fbd6a042bb24879e57d474fb5" +checksum = "e575fab7d1e0dcb8d0c7bcf9a63ee213816ab51902e6d244a95819acacf1d4f7" [[package]] name = "futures-task" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38d84fa142264698cdce1a9f9172cf383a0c82de1bddcf3092901442c4097004" +checksum = "f90f7dce0722e95104fcb095585910c0977252f286e354b5e3bd38902cd99988" [[package]] name = "futures-util" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d6401deb83407ab3da39eba7e33987a73c3df0c82b4bb5813ee871c19c41d48" +checksum = "9fa08315bb612088cc391249efdc3bc77536f16c91f6cf495e6fbe85b20a4a81" dependencies = [ "futures-channel", "futures-core", @@ -836,28 +552,9 @@ dependencies = [ [[package]] name = "gimli" -version = "0.29.0" +version = "0.31.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "40ecd4077b5ae9fd2e9e169b102c6c330d0605168eb0e8bf79952b256dbefffd" - -[[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 0.2.12", - "indexmap", - "slab", - "tokio", - "tokio-util", - "tracing", -] +checksum = "07e28edb80900c19c28f1072f2e8aeca7fa06b23cd4169cefe1af5aa3260783f" [[package]] name = "h2" @@ -870,7 +567,7 @@ dependencies = [ "fnv", "futures-core", "futures-sink", - "http 1.1.0", + "http", "indexmap", "slab", "tokio", @@ -880,9 +577,9 @@ dependencies = [ [[package]] name = "hashbrown" -version = "0.14.5" +version = "0.15.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" +checksum = "3a9bfc1af68b1726ea47d3d5109de126281def866b33970e10fbab11b5dafab3" [[package]] name = "hermit-abi" @@ -890,17 +587,6 @@ version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024" -[[package]] -name = "http" -version = "0.2.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "601cbb57e577e2f5ef5be8e7b83f0f63994f25aa94d673e54a92d5c516d101f1" -dependencies = [ - "bytes", - "fnv", - "itoa", -] - [[package]] name = "http" version = "1.1.0" @@ -919,7 +605,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1efedce1fb8e6913f23e0c92de8e62cd5b772a67e7b3946df930a62566c93184" dependencies = [ "bytes", - "http 1.1.0", + "http", ] [[package]] @@ -930,22 +616,16 @@ checksum = "793429d76616a256bcb62c2a2ec2bed781c8307e797e2598c50010f2bee2544f" dependencies = [ "bytes", "futures-util", - "http 1.1.0", + "http", "http-body", "pin-project-lite", ] -[[package]] -name = "http-range" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "21dec9db110f5f872ed9699c3ecf50cf16f423502706ba5c72462e28d3157573" - [[package]] name = "httparse" -version = "1.9.4" +version = "1.9.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fcc0b4a115bf80b728eb8ea024ad5bd707b615bfed49e0665b6e0f86fd082d9" +checksum = "7d71d3574edd2771538b901e6549113b4006ece66150fb69c0fb6d9a2adae946" [[package]] name = "httpdate" @@ -953,25 +633,20 @@ version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9" -[[package]] -name = "humantime" -version = "2.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4" - [[package]] name = "hyper" -version = "1.4.1" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "50dfd22e0e76d0f662d429a5f80fcaf3855009297eab6a0a9f8543834744ba05" +checksum = "bbbff0a806a4728c99295b254c8838933b5b082d75e3cb70c8dab21fdfbcfa9a" dependencies = [ "bytes", "futures-channel", "futures-util", - "h2 0.4.6", - "http 1.1.0", + "h2", + "http", "http-body", "httparse", + "httpdate", "itoa", "pin-project-lite", "smallvec", @@ -986,7 +661,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "08afdbb5c31130e3034af566421053ab03787c640246a446327f550d11bcb333" dependencies = [ "futures-util", - "http 1.1.0", + "http", "hyper", "hyper-util", "rustls", @@ -1014,45 +689,167 @@ dependencies = [ [[package]] name = "hyper-util" -version = "0.1.7" +version = "0.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cde7055719c54e36e95e8719f95883f22072a48ede39db7fc17a4e1d5281e9b9" +checksum = "df2dcfbe0677734ab2f3ffa7fa7bfd4706bfdc1ef393f2ee30184aed67e631b4" dependencies = [ "bytes", "futures-channel", "futures-util", - "http 1.1.0", + "http", "http-body", "hyper", "pin-project-lite", "socket2", "tokio", - "tower", "tower-service", "tracing", ] +[[package]] +name = "icu_collections" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "db2fa452206ebee18c4b5c2274dbf1de17008e874b4dc4f0aea9d01ca79e4526" +dependencies = [ + "displaydoc", + "yoke", + "zerofrom", + "zerovec", +] + +[[package]] +name = "icu_locid" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13acbb8371917fc971be86fc8057c41a64b521c184808a698c02acc242dbf637" +dependencies = [ + "displaydoc", + "litemap", + "tinystr", + "writeable", + "zerovec", +] + +[[package]] +name = "icu_locid_transform" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "01d11ac35de8e40fdeda00d9e1e9d92525f3f9d887cdd7aa81d727596788b54e" +dependencies = [ + "displaydoc", + "icu_locid", + "icu_locid_transform_data", + "icu_provider", + "tinystr", + "zerovec", +] + +[[package]] +name = "icu_locid_transform_data" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fdc8ff3388f852bede6b579ad4e978ab004f139284d7b28715f773507b946f6e" + +[[package]] +name = "icu_normalizer" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "19ce3e0da2ec68599d193c93d088142efd7f9c5d6fc9b803774855747dc6a84f" +dependencies = [ + "displaydoc", + "icu_collections", + "icu_normalizer_data", + "icu_properties", + "icu_provider", + "smallvec", + "utf16_iter", + "utf8_iter", + "write16", + "zerovec", +] + +[[package]] +name = "icu_normalizer_data" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8cafbf7aa791e9b22bec55a167906f9e1215fd475cd22adfcf660e03e989516" + +[[package]] +name = "icu_properties" +version = "1.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93d6020766cfc6302c15dbbc9c8778c37e62c14427cb7f6e601d849e092aeef5" +dependencies = [ + "displaydoc", + "icu_collections", + "icu_locid_transform", + "icu_properties_data", + "icu_provider", + "tinystr", + "zerovec", +] + +[[package]] +name = "icu_properties_data" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67a8effbc3dd3e4ba1afa8ad918d5684b8868b3b26500753effea8d2eed19569" + +[[package]] +name = "icu_provider" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ed421c8a8ef78d3e2dbc98a973be2f3770cb42b606e3ab18d6237c4dfde68d9" +dependencies = [ + "displaydoc", + "icu_locid", + "icu_provider_macros", + "stable_deref_trait", + "tinystr", + "writeable", + "yoke", + "zerofrom", + "zerovec", +] + +[[package]] +name = "icu_provider_macros" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ec89e9337638ecdc08744df490b221a7399bf8d164eb52a665454e60e075ad6" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "idna" -version = "0.5.0" +version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "634d9b1461af396cad843f47fdba5597a4f9e6ddd4bfb6ff5d85028c25cb12f6" +checksum = "686f825264d630750a544639377bae737628043f20d38bbc029e8f29ea968a7e" dependencies = [ - "unicode-bidi", - "unicode-normalization", + "idna_adapter", + "smallvec", + "utf8_iter", ] [[package]] -name = "impl-more" -version = "0.1.6" +name = "idna_adapter" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "206ca75c9c03ba3d4ace2460e57b189f39f43de612c2f85836e65c929701bb2d" +checksum = "daca1df1c957320b2cf139ac61e7bd64fed304c5040df000a745aa1de3b4ef71" +dependencies = [ + "icu_normalizer", + "icu_properties", +] [[package]] name = "indexmap" -version = "2.5.0" +version = "2.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "68b900aa2f7301e21c36462b170ee99994de34dff39a4a6a528e80e7376d07e5" +checksum = "707907fe3c25f5424cce2cb7e1cbcafee6bdbe735ca90ef77c29e84591e5b9da" dependencies = [ "equivalent", "hashbrown", @@ -1069,15 +866,9 @@ dependencies = [ [[package]] name = "ipnet" -version = "2.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "187674a687eed5fe42285b40c6291f9a01517d415fad1c3cbc6a9f778af7fcd4" - -[[package]] -name = "is_terminal_polyfill" -version = "1.70.1" +version = "2.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7943c866cc5cd64cbc25b2e01621d07fa8eb2a1a23160ee81ce38704e97b8ecf" +checksum = "ddc24109865250148c2e0f3d25d4f0f479571723792d3802153c60922a4fb708" [[package]] name = "itoa" @@ -1085,35 +876,26 @@ version = "1.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b" -[[package]] -name = "jobserver" -version = "0.1.32" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "48d1dbcbbeb6a7fec7e059840aa538bd62aaccf972c7346c4d9d2059312853d0" -dependencies = [ - "libc", -] - [[package]] name = "js-sys" -version = "0.3.70" +version = "0.3.72" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1868808506b929d7b0cfa8f75951347aa71bb21144b7791bae35d9bccfcfe37a" +checksum = "6a88f1bda2bd75b0452a14784937d796722fdebfe50df998aeb3f0b7603019a9" dependencies = [ "wasm-bindgen", ] [[package]] -name = "language-tags" -version = "0.3.2" +name = "lazy_static" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d4345964bb142484797b161f473a503a434de77149dd8c7427788c6e13379388" +checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" [[package]] name = "libc" -version = "0.2.158" +version = "0.2.162" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d8adc4bb1803a324070e64a98ae98f38934d91957a99cfb3a43dcbc01bc56439" +checksum = "18d287de67fe55fd7e1581fe933d965a5a9477b38e949cfa9f8574ef01506398" [[package]] name = "libredox" @@ -1133,31 +915,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "78b3ae25bc7c8c38cec158d1f2757ee79e9b3740fbc7ccf0e59e4b08d793fa89" [[package]] -name = "local-channel" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6cbc85e69b8df4b8bb8b89ec634e7189099cea8927a276b7384ce5488e53ec8" -dependencies = [ - "futures-core", - "futures-sink", - "local-waker", -] - -[[package]] -name = "local-waker" -version = "0.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4d873d7c67ce09b42110d801813efbc9364414e356be9935700d368351657487" - -[[package]] -name = "lock_api" -version = "0.4.12" +name = "litemap" +version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07af8b9cdd281b7915f413fa73f29ebd5d55d0d3f0155584dade1ff18cea1b17" -dependencies = [ - "autocfg", - "scopeguard", -] +checksum = "643cb0b8d4fcc284004d5fd0d67ccf61dfffadb7f75e1e71bc420f4688a3a704" [[package]] name = "log" @@ -1177,35 +938,22 @@ dependencies = [ ] [[package]] -name = "memchr" -version = "2.7.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" - -[[package]] -name = "mime" -version = "0.3.17" +name = "matchit" +version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a" +checksum = "0e7465ac9959cc2b1404e8e2367b43684a6d13790fe23056cc8c6c5a6b7bcb94" [[package]] -name = "mime_guess" -version = "2.0.5" +name = "memchr" +version = "2.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f7c44f8e672c00fe5308fa235f821cb4198414e1c77935c1ab6948d3fd78550e" -dependencies = [ - "mime", - "unicase", -] +checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" [[package]] -name = "miniz_oxide" -version = "0.7.4" +name = "mime" +version = "0.3.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b8a240ddb74feaf34a79a7add65a741f3167852fba007066dcac1ca548d89c08" -dependencies = [ - "adler", -] +checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a" [[package]] name = "miniz_oxide" @@ -1224,7 +972,6 @@ checksum = "80e04d1dcff3aae0704555fe5fee3bcfaf3d1fdf8a7e521d5b9d2b42acb52cec" dependencies = [ "hermit-abi", "libc", - "log", "wasi", "windows-sys 0.52.0", ] @@ -1247,31 +994,35 @@ dependencies = [ ] [[package]] -name = "num-conv" -version = "0.1.0" +name = "nu-ansi-term" +version = "0.46.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "51d515d32fb182ee37cda2ccdcb92950d6a3c2893aa280e540671c2cd0f3b1d9" +checksum = "77a8165726e8236064dbb45459242600304b42a5ea24ee2948e18e023bf7ba84" +dependencies = [ + "overload", + "winapi", +] [[package]] name = "object" -version = "0.36.4" +version = "0.36.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "084f1a5821ac4c651660a94a7153d27ac9d8a53736203f58b31945ded098070a" +checksum = "aedf0a2d09c573ed1d8d85b30c119153926a2b36dce0ab28322c09a117a4683e" dependencies = [ "memchr", ] [[package]] name = "once_cell" -version = "1.19.0" +version = "1.20.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" +checksum = "1261fe7e33c73b354eab43b1273a57c8f967d0391e80353e51f764ac02cf6775" [[package]] name = "openssl" -version = "0.10.66" +version = "0.10.68" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9529f4786b70a3e8c61e11179af17ab6188ad8d0ded78c5529441ed39d4bd9c1" +checksum = "6174bc48f102d208783c2c84bf931bb75927a617866870de8a4ea85597f871f5" dependencies = [ "bitflags", "cfg-if", @@ -1301,9 +1052,9 @@ checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf" [[package]] name = "openssl-sys" -version = "0.9.103" +version = "0.9.104" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f9e8deee91df40a943c71b917e5874b951d32a802526c85721ce3b776c929d6" +checksum = "45abf306cbf99debc8195b66b7346498d7b10c210de50418b5ccd7ceba08c741" dependencies = [ "cc", "libc", @@ -1312,65 +1063,33 @@ dependencies = [ ] [[package]] -name = "parking_lot" -version = "0.12.3" +name = "overload" +version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1bf18183cf54e8d6059647fc3063646a1801cf30896933ec2311622cc4b9a27" -dependencies = [ - "lock_api", - "parking_lot_core", -] +checksum = "b15813163c1d831bf4a13c3610c05c0d03b39feb07f7e09fa234dac9b15aaf39" [[package]] -name = "parking_lot_core" -version = "0.9.10" +name = "password-hash" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e401f977ab385c9e4e3ab30627d6f26d00e2c73eef317493c4ec6d468726cf8" +checksum = "346f04948ba92c43e8469c1ee6736c7563d71012b17d40745260fe106aac2166" dependencies = [ - "cfg-if", - "libc", - "redox_syscall", - "smallvec", - "windows-targets", + "base64ct", + "rand_core", + "subtle", ] -[[package]] -name = "paste" -version = "1.0.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a" - [[package]] name = "percent-encoding" version = "2.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" -[[package]] -name = "pin-project" -version = "1.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6bf43b791c5b9e34c3d182969b4abb522f9343702850a2e57f460d00d09b4b3" -dependencies = [ - "pin-project-internal", -] - -[[package]] -name = "pin-project-internal" -version = "1.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2f38a4412a78282e09a2cf38d195ea5420d15ba0602cb375210efbc877243965" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - [[package]] name = "pin-project-lite" -version = "0.2.14" +version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bda66fc9667c18cb2758a2ac84d1167245054bcf85d5d1aaa6923f45801bdd02" +checksum = "915a1e146535de9163f3987b8944ed8cf49a18bb0056bcebcdcece385cece4ff" [[package]] name = "pin-utils" @@ -1380,15 +1099,9 @@ checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" [[package]] name = "pkg-config" -version = "0.3.30" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d231b230927b5e4ad203db57bbcbee2802f6bce620b1e4a9024a07d94e2907ec" - -[[package]] -name = "powerfmt" -version = "0.2.0" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391" +checksum = "953ec861398dccce10c670dfeaf3ec4911ca479e9c02154b3a215178c5f566f2" [[package]] name = "ppv-lite86" @@ -1401,9 +1114,9 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.86" +version = "1.0.89" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5e719e8df665df0d1c8fbfd238015744736151d4445ec0836b8e628aae103b77" +checksum = "f139b0662de085916d1fb67d2b4169d1addddda1919e696f3252b740b629986e" dependencies = [ "unicode-ident", ] @@ -1449,62 +1162,26 @@ dependencies = [ [[package]] name = "redox_syscall" -version = "0.5.3" +version = "0.5.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2a908a6e00f1fdd0dfd9c0eb08ce85126f6d8bbda50017e74bc4a4b7d4a926a4" +checksum = "9b6dfecf2c74bce2466cabf93f6664d6998a69eb21e39f4207930065b27b771f" dependencies = [ "bitflags", ] -[[package]] -name = "regex" -version = "1.10.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4219d74c6b67a3654a9fbebc4b419e22126d13d2f3c4a07ee0cb61ff79a79619" -dependencies = [ - "aho-corasick", - "memchr", - "regex-automata", - "regex-syntax", -] - -[[package]] -name = "regex-automata" -version = "0.4.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38caf58cc5ef2fed281f89292ef23f6365465ed9a41b7a7754eb4e26496c92df" -dependencies = [ - "aho-corasick", - "memchr", - "regex-syntax", -] - -[[package]] -name = "regex-lite" -version = "0.1.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "53a49587ad06b26609c52e423de037e7f57f20d53535d66e08c695f347df952a" - -[[package]] -name = "regex-syntax" -version = "0.8.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a66a03ae7c801facd77a29370b4faec201768915ac14a721ba36f20bc9c209b" - [[package]] name = "reqwest" -version = "0.12.7" +version = "0.12.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f8f4955649ef5c38cc7f9e8aa41761d48fb9677197daea9984dc54f56aad5e63" +checksum = "a77c62af46e79de0a562e1a9849205ffcb7fc1238876e9bd743357570e04046f" dependencies = [ "base64", "bytes", "encoding_rs", - "futures-channel", "futures-core", "futures-util", - "h2 0.4.6", - "http 1.1.0", + "h2", + "http", "http-body", "http-body-util", "hyper", @@ -1523,7 +1200,7 @@ dependencies = [ "serde", "serde_json", "serde_urlencoded", - "sync_wrapper", + "sync_wrapper 1.0.1", "system-configuration", "tokio", "tokio-native-tls", @@ -1558,20 +1235,11 @@ version = "0.1.24" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f" -[[package]] -name = "rustc_version" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cfcb3a22ef46e85b45de6ee7e79d063319ebb6594faafcf1c225ea92ab6e9b92" -dependencies = [ - "semver", -] - [[package]] name = "rustix" -version = "0.38.36" +version = "0.38.39" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f55e80d50763938498dd5ebb18647174e0c76dc38c5505294bb224624f30f36" +checksum = "375116bee2be9ed569afe2154ea6a99dfdffd257f533f187498c2a8f5feaf4ee" dependencies = [ "bitflags", "errno", @@ -1582,9 +1250,9 @@ dependencies = [ [[package]] name = "rustls" -version = "0.23.12" +version = "0.23.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c58f8c84392efc0a126acce10fa59ff7b3d2ac06ab451a33f2741989b806b044" +checksum = "eee87ff5d9b36712a58574e12e9f0ea80f915a5b0ac518d322b24a465617925e" dependencies = [ "once_cell", "rustls-pki-types", @@ -1595,31 +1263,36 @@ dependencies = [ [[package]] name = "rustls-pemfile" -version = "2.1.3" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "196fe16b00e106300d3e45ecfcb764fa292a535d7326a29a5875c579c7417425" +checksum = "dce314e5fee3f39953d46bb63bb8a46d40c2f8fb7cc5a3b6cab2bde9721d6e50" dependencies = [ - "base64", "rustls-pki-types", ] [[package]] name = "rustls-pki-types" -version = "1.8.0" +version = "1.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fc0a2ce646f8655401bb81e7927b812614bd5d91dbc968696be50603510fcaf0" +checksum = "16f1201b3c9a7ee8039bcadc17b7e605e2945b27eee7631788c1bd2b0643674b" [[package]] name = "rustls-webpki" -version = "0.102.7" +version = "0.102.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "84678086bd54edf2b415183ed7a94d0efb049f1b646a33e22a36f3794be6ae56" +checksum = "64ca1bc8749bd4cf37b5ce386cc146580777b4e8572c7b97baf22c83f444bee9" dependencies = [ "ring", "rustls-pki-types", "untrusted", ] +[[package]] +name = "rustversion" +version = "1.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0e819f2bc632f285be6d7cd36e25940d45b2391dd6d9b939e79de557f7014248" + [[package]] name = "ryu" version = "1.0.18" @@ -1628,19 +1301,13 @@ checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f" [[package]] name = "schannel" -version = "0.1.24" +version = "0.1.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e9aaafd5a2b6e3d657ff009d82fbd630b6bd54dd4eb06f21693925cdf80f9b8b" +checksum = "01227be5826fa0690321a2ba6c5cd57a19cf3f6a09e76973b58e61de6ab9d1c1" dependencies = [ "windows-sys 0.59.0", ] -[[package]] -name = "scopeguard" -version = "1.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" - [[package]] name = "security-framework" version = "2.11.1" @@ -1656,34 +1323,28 @@ dependencies = [ [[package]] name = "security-framework-sys" -version = "2.11.1" +version = "2.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "75da29fe9b9b08fe9d6b22b5b4bcbc75d8db3aa31e639aa56bb62e9d46bfceaf" +checksum = "fa39c7303dc58b5543c94d22c1766b0d31f2ee58306363ea622b10bbc075eaa2" dependencies = [ "core-foundation-sys", "libc", ] -[[package]] -name = "semver" -version = "1.0.23" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "61697e0a1c7e512e84a621326239844a24d8207b4669b41bc18b32ea5cbf988b" - [[package]] name = "serde" -version = "1.0.210" +version = "1.0.214" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c8e3592472072e6e22e0a54d5904d9febf8508f65fb8552499a1abc7d1078c3a" +checksum = "f55c3193aca71c12ad7890f1785d2b73e1b9f63a0bbc353c08ef26fe03fc56b5" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.210" +version = "1.0.214" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "243902eda00fad750862fc144cea25caca5e20d615af0a81bee94ca738f1df1f" +checksum = "de523f781f095e28fa605cdce0f8307e451cc0fd14e2eb4cd2e98a355b147766" dependencies = [ "proc-macro2", "quote", @@ -1692,9 +1353,9 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.128" +version = "1.0.132" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ff5456707a1de34e7e37f2a6fd3d3f808c318259cbd01ab6377795054b483d8" +checksum = "d726bfaff4b320266d395898905d0eba0345aae23b54aee3a737e260fd46db03" dependencies = [ "itoa", "memchr", @@ -1702,6 +1363,16 @@ dependencies = [ "serde", ] +[[package]] +name = "serde_path_to_error" +version = "0.1.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "af99884400da37c88f5e9146b7f1fd0fbcae8f6eec4e9da38b67d05486f814a6" +dependencies = [ + "itoa", + "serde", +] + [[package]] name = "serde_urlencoded" version = "0.7.1" @@ -1715,14 +1386,12 @@ dependencies = [ ] [[package]] -name = "sha1" -version = "0.10.6" +name = "sharded-slab" +version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3bf829a2d51ab4a5ddf1352d8470c140cadc8301b2ae1789db023f01cedd6ba" +checksum = "f40ca3c46823713e0d4209592e8d6e826aa57e928f09752619fc696c499637f6" dependencies = [ - "cfg-if", - "cpufeatures", - "digest", + "lazy_static", ] [[package]] @@ -1731,15 +1400,6 @@ version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" -[[package]] -name = "signal-hook-registry" -version = "1.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a9e9e0b4211b72e7b8b6e85c807d36c212bdb33ea8587f7569562a84df5465b1" -dependencies = [ - "libc", -] - [[package]] name = "slab" version = "0.4.9" @@ -1771,6 +1431,12 @@ version = "0.9.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67" +[[package]] +name = "stable_deref_trait" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" + [[package]] name = "subtle" version = "2.6.1" @@ -1779,15 +1445,21 @@ checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" [[package]] name = "syn" -version = "2.0.77" +version = "2.0.87" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9f35bcdf61fd8e7be6caf75f429fdca8beb3ed76584befb503b1569faee373ed" +checksum = "25aa4ce346d03a6dcd68dd8b4010bcb74e54e62c90c573f394c46eae99aba32d" dependencies = [ "proc-macro2", "quote", "unicode-ident", ] +[[package]] +name = "sync_wrapper" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2047c6ded9c721764247e62cd3b03c09ffc529b2ba5b10ec482ae507a4a70160" + [[package]] name = "sync_wrapper" version = "1.0.1" @@ -1797,6 +1469,17 @@ dependencies = [ "futures-core", ] +[[package]] +name = "synstructure" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c8af7666ab7b6390ab78131fb5b0fce11d6b7a6951602017c35fa82800708971" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "system-configuration" version = "0.6.1" @@ -1820,9 +1503,9 @@ dependencies = [ [[package]] name = "tar" -version = "0.4.41" +version = "0.4.43" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cb797dad5fb5b76fcf519e702f4a589483b5ef06567f160c392832c1f5e44909" +checksum = "c65998313f8e17d0d553d28f91a0df93e4dbbbf770279c7bc21ca0f09ea1a1f6" dependencies = [ "filetime", "libc", @@ -1831,9 +1514,9 @@ dependencies = [ [[package]] name = "tempfile" -version = "3.12.0" +version = "3.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "04cbcdd0c794ebb0d4cf35e88edd2f7d2c4c3e9a5a6dab322839b321c6a87a64" +checksum = "28cce251fcbc87fac86a866eeb0d6c2d536fc16d06f184bb61aeae11aa4cee0c" dependencies = [ "cfg-if", "fastrand", @@ -1843,64 +1526,36 @@ dependencies = [ ] [[package]] -name = "time" -version = "0.3.36" +name = "thread_local" +version = "1.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5dfd88e563464686c916c7e46e623e520ddc6d79fa6641390f2e3fa86e83e885" +checksum = "8b9ef9bad013ada3808854ceac7b46812a6465ba368859a37e2100283d2d719c" dependencies = [ - "deranged", - "itoa", - "num-conv", - "powerfmt", - "serde", - "time-core", - "time-macros", -] - -[[package]] -name = "time-core" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ef927ca75afb808a4d64dd374f00a2adf8d0fcff8e7b184af886c3c87ec4a3f3" - -[[package]] -name = "time-macros" -version = "0.2.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f252a68540fde3a3877aeea552b832b40ab9a69e318efd078774a01ddee1ccf" -dependencies = [ - "num-conv", - "time-core", + "cfg-if", + "once_cell", ] [[package]] -name = "tinyvec" -version = "1.8.0" +name = "tinystr" +version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "445e881f4f6d382d5f27c034e25eb92edd7c784ceab92a0937db7f2e9471b938" +checksum = "9117f5d4db391c1cf6927e7bea3db74b9a1c1add8f7eda9ffd5364f40f57b82f" dependencies = [ - "tinyvec_macros", + "displaydoc", + "zerovec", ] -[[package]] -name = "tinyvec_macros" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" - [[package]] name = "tokio" -version = "1.40.0" +version = "1.41.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2b070231665d27ad9ec9b8df639893f46727666c6767db40317fbe920a5d998" +checksum = "22cfb5bee7a6a52939ca9224d6ac897bb669134078daa8735560897f69de4d33" dependencies = [ "backtrace", "bytes", "libc", "mio", - "parking_lot", "pin-project-lite", - "signal-hook-registry", "socket2", "tokio-macros", "windows-sys 0.52.0", @@ -1953,17 +1608,18 @@ dependencies = [ [[package]] name = "tower" -version = "0.4.13" +version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b8fa9be0de6cf49e536ce1851f987bd21a43b771b09473c3549a6c853db37c1c" +checksum = "2873938d487c3cfb9aed7546dc9f2711d867c9f90c46b889989a2cb84eba6b4f" dependencies = [ "futures-core", "futures-util", - "pin-project", "pin-project-lite", + "sync_wrapper 0.1.2", "tokio", "tower-layer", "tower-service", + "tracing", ] [[package]] @@ -1986,9 +1642,21 @@ checksum = "c3523ab5a71916ccf420eebdf5521fcef02141234bbc0b8a49f2fdc4544364ef" dependencies = [ "log", "pin-project-lite", + "tracing-attributes", "tracing-core", ] +[[package]] +name = "tracing-attributes" +version = "0.1.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "tracing-core" version = "0.1.32" @@ -1996,49 +1664,51 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c06d3da6113f116aaee68e4d601191614c9053067f9ab7f6edbcb161237daa54" dependencies = [ "once_cell", + "valuable", ] [[package]] -name = "try-lock" -version = "0.2.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b" - -[[package]] -name = "typenum" -version = "1.17.0" +name = "tracing-log" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825" +checksum = "ee855f1f400bd0e5c02d150ae5de3840039a3f54b025156404e34c23c03f47c3" +dependencies = [ + "log", + "once_cell", + "tracing-core", +] [[package]] -name = "unicase" -version = "2.7.0" +name = "tracing-subscriber" +version = "0.3.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f7d2d4dafb69621809a81864c9c1b864479e1235c0dd4e199924b9742439ed89" +checksum = "ad0f048c97dbd9faa9b7df56362b8ebcaa52adb06b498c050d2f4e32f90a7a8b" dependencies = [ - "version_check", + "nu-ansi-term", + "sharded-slab", + "smallvec", + "thread_local", + "tracing-core", + "tracing-log", ] [[package]] -name = "unicode-bidi" -version = "0.3.15" +name = "try-lock" +version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08f95100a766bf4f8f28f90d77e0a5461bbdb219042e7679bebe79004fed8d75" +checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b" [[package]] -name = "unicode-ident" -version = "1.0.12" +name = "typenum" +version = "1.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" +checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825" [[package]] -name = "unicode-normalization" -version = "0.1.23" +name = "unicode-ident" +version = "1.0.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a56d1686db2308d901306f92a263857ef59ea39678a5458e7cb17f01415101f5" -dependencies = [ - "tinyvec", -] +checksum = "e91b56cd4cadaeb79bbf1a5645f6b4f8dc5bde8834ad5894a8db35fda9efa1fe" [[package]] name = "untrusted" @@ -2048,9 +1718,9 @@ checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" [[package]] name = "url" -version = "2.5.2" +version = "2.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22784dbdf76fdde8af1aeda5622b546b422b6fc585325248a2bf9f5e41e94d6c" +checksum = "8d157f1b96d14500ffdc1f10ba712e780825526c03d9a49b4d0324b0d9113ada" dependencies = [ "form_urlencoded", "idna", @@ -2058,22 +1728,38 @@ dependencies = [ ] [[package]] -name = "utf8parse" -version = "0.2.2" +name = "utf16_iter" +version = "1.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c8232dd3cdaed5356e0f716d285e4b40b932ac434100fe9b7e0e8e935b9e6246" + +[[package]] +name = "utf8_iter" +version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" +checksum = "b6c140620e7ffbb22c2dee59cafe6084a59b5ffc27a8859a5f0d494b5d52b6be" + +[[package]] +name = "utils" +version = "0.1.0" +source = "git+https://github.com/maestro-os/maestro-utils#53e7e8928457f68e46773eaf94ef6c09b2859cc9" +dependencies = [ + "argon2", + "libc", + "rand_core", +] [[package]] name = "uuid" -version = "1.10.0" +version = "1.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "81dfa00651efa65069b0b6b651f4aaa31ba9e3c3ce0137aaad053604ee7e0314" +checksum = "f8c5f0a0af699448548ad1a2fbf920fb4bee257eae39953ba95cb84891a0446a" [[package]] -name = "v_htmlescape" -version = "0.15.8" +name = "valuable" +version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4e8257fbc510f0a46eb602c10215901938b5c2a7d5e70fc11483b1d3c9b5b18c" +checksum = "830b7e5d4d90034032940e4ace0d9a9a057e7a45cd94e6c007832e39edb82f6d" [[package]] name = "vcpkg" @@ -2104,9 +1790,9 @@ checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" [[package]] name = "wasm-bindgen" -version = "0.2.93" +version = "0.2.95" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a82edfc16a6c469f5f44dc7b571814045d60404b55a0ee849f9bcfa2e63dd9b5" +checksum = "128d1e363af62632b8eb57219c8fd7877144af57558fb2ef0368d0087bddeb2e" dependencies = [ "cfg-if", "once_cell", @@ -2115,9 +1801,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-backend" -version = "0.2.93" +version = "0.2.95" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9de396da306523044d3302746f1208fa71d7532227f15e347e2d93e4145dd77b" +checksum = "cb6dd4d3ca0ddffd1dd1c9c04f94b868c37ff5fac97c30b97cff2d74fce3a358" dependencies = [ "bumpalo", "log", @@ -2130,9 +1816,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-futures" -version = "0.4.43" +version = "0.4.45" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "61e9300f63a621e96ed275155c108eb6f843b6a26d053f122ab69724559dc8ed" +checksum = "cc7ec4f8827a71586374db3e87abdb5a2bb3a15afed140221307c3ec06b1f63b" dependencies = [ "cfg-if", "js-sys", @@ -2142,9 +1828,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.93" +version = "0.2.95" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "585c4c91a46b072c92e908d99cb1dcdf95c5218eeb6f3bf1efa991ee7a68cccf" +checksum = "e79384be7f8f5a9dd5d7167216f022090cf1f9ec128e6e6a482a2cb5c5422c56" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -2152,9 +1838,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.93" +version = "0.2.95" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "afc340c74d9005395cf9dd098506f7f44e38f2b4a21c6aaacf9a105ea5e1e836" +checksum = "26c6ab57572f7a24a4985830b120de1594465e5d500f24afe89e16b4e833ef68" dependencies = [ "proc-macro2", "quote", @@ -2165,15 +1851,15 @@ dependencies = [ [[package]] name = "wasm-bindgen-shared" -version = "0.2.93" +version = "0.2.95" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c62a0a307cb4a311d3a07867860911ca130c3494e8c2719593806c08bc5d0484" +checksum = "65fc09f10666a9f147042251e0dda9c18f166ff7de300607007e96bdebc1068d" [[package]] name = "wasm-streams" -version = "0.4.0" +version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b65dc4c90b63b118468cf747d8bf3566c1913ef60be765b5730ead9e0a3ba129" +checksum = "15053d8d85c7eccdbefef60f06769760a563c7f0a9d6902a13d35c7800b0ad65" dependencies = [ "futures-util", "js-sys", @@ -2184,14 +1870,36 @@ dependencies = [ [[package]] name = "web-sys" -version = "0.3.70" +version = "0.3.72" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26fdeaafd9bd129f65e7c031593c24d62186301e0c72c8978fa1678be7d532c0" +checksum = "f6488b90108c040df0fe62fa815cbdee25124641df01814dd7282749234c6112" dependencies = [ "js-sys", "wasm-bindgen", ] +[[package]] +name = "winapi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" +dependencies = [ + "winapi-i686-pc-windows-gnu", + "winapi-x86_64-pc-windows-gnu", +] + +[[package]] +name = "winapi-i686-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" + +[[package]] +name = "winapi-x86_64-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" + [[package]] name = "windows-registry" version = "0.2.0" @@ -2304,6 +2012,18 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" +[[package]] +name = "write16" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d1890f4022759daae28ed4fe62859b1236caebfc61ede2f63ed4e695f3f6d936" + +[[package]] +name = "writeable" +version = "0.5.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e9df38ee2d2c3c5948ea468a8406ff0db0b29ae1ffde1bcf20ef305bcc95c51" + [[package]] name = "xattr" version = "1.3.1" @@ -2324,6 +2044,30 @@ dependencies = [ "lzma-sys", ] +[[package]] +name = "yoke" +version = "0.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c5b1314b079b0930c31e3af543d8ee1757b1951ae1e1565ec704403a7240ca5" +dependencies = [ + "serde", + "stable_deref_trait", + "yoke-derive", + "zerofrom", +] + +[[package]] +name = "yoke-derive" +version = "0.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "28cc31741b18cb6f1d5ff12f5b7523e3d6eb0852bbbad19d73905511d9849b95" +dependencies = [ + "proc-macro2", + "quote", + "syn", + "synstructure", +] + [[package]] name = "zerocopy" version = "0.7.35" @@ -2346,35 +2090,50 @@ dependencies = [ ] [[package]] -name = "zeroize" -version = "1.8.1" +name = "zerofrom" +version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ced3678a2879b30306d323f4542626697a464a97c0a07c9aebf7ebca65cd4dde" +checksum = "91ec111ce797d0e0784a1116d0ddcdbea84322cd79e5d5ad173daeba4f93ab55" +dependencies = [ + "zerofrom-derive", +] [[package]] -name = "zstd" -version = "0.13.2" +name = "zerofrom-derive" +version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fcf2b778a664581e31e389454a7072dab1647606d44f7feea22cd5abb9c9f3f9" +checksum = "0ea7b4a3637ea8669cedf0f1fd5c286a17f3de97b8dd5a70a6c167a1730e63a5" dependencies = [ - "zstd-safe", + "proc-macro2", + "quote", + "syn", + "synstructure", ] [[package]] -name = "zstd-safe" -version = "7.2.1" +name = "zeroize" +version = "1.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ced3678a2879b30306d323f4542626697a464a97c0a07c9aebf7ebca65cd4dde" + +[[package]] +name = "zerovec" +version = "0.10.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "54a3ab4db68cea366acc5c897c7b4d4d1b8994a9cd6e6f841f8964566a419059" +checksum = "aa2b893d79df23bfb12d5461018d408ea19dfafe76c2c7ef6d4eba614f8ff079" dependencies = [ - "zstd-sys", + "yoke", + "zerofrom", + "zerovec-derive", ] [[package]] -name = "zstd-sys" -version = "2.0.13+zstd.1.5.6" +name = "zerovec-derive" +version = "0.10.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38ff0f21cfee8f97d94cef41359e0c89aa6113028ab0291aa8ca0038995a95aa" +checksum = "6eafa6dfb17584ea3e2bd6e76e0cc15ad7af12b09abdd1ca55961bed9b1063c6" dependencies = [ - "cc", - "pkg-config", + "proc-macro2", + "quote", + "syn", ] diff --git a/builder/src/build.rs b/builder/src/build.rs index c7c310b..a56b4c2 100644 --- a/builder/src/build.rs +++ b/builder/src/build.rs @@ -1,18 +1,18 @@ //! Implementation of the package building procedure. -use crate::desc::BuildDescriptor; -use crate::WORK_DIR; +use crate::{desc::BuildDescriptor, WORK_DIR}; use anyhow::Result; -use flate2::write::GzEncoder; -use flate2::Compression; -use std::fs; -use std::fs::File; -use std::io; -use std::path::Path; -use std::path::PathBuf; -use std::process::Command; -use std::str; -use std::sync::Arc; +use common::serde_json; +use flate2::{write::GzEncoder, Compression}; +use std::{ + fs, + fs::File, + io, + path::{Path, PathBuf}, + process::Command, + str, + sync::Arc, +}; /// A build process is the operation of converting source code into an installable package. /// @@ -38,7 +38,8 @@ impl BuildProcess { /// `input_path` is the path to the directory containing information to build the package. pub fn new(input_path: PathBuf) -> io::Result { let build_desc_path = input_path.join("package.json"); - let build_desc = common::util::read_json::(&build_desc_path)?; + let build_desc = fs::read_to_string(build_desc_path)?; + let build_desc = serde_json::from_str(&build_desc)?; Ok(Self { input_path, build_desc, @@ -98,12 +99,9 @@ impl BuildProcess { .env("HOST", host) .env("TARGET", target) .env("SYSROOT", &self.sysroot) - .env("PKG_NAME", self.build_desc.package.get_name()) - .env( - "PKG_VERSION", - self.build_desc.package.get_version().to_string(), - ) - .env("PKG_DESC", self.build_desc.package.get_description()) + .env("PKG_NAME", &self.build_desc.package.name) + .env("PKG_VERSION", self.build_desc.package.version.to_string()) + .env("PKG_DESC", &self.build_desc.package.description) .env("JOBS", jobs.to_string()) .current_dir(&self.build_dir) .status() diff --git a/builder/src/desc.rs b/builder/src/desc.rs index df15ce1..749d6c7 100644 --- a/builder/src/desc.rs +++ b/builder/src/desc.rs @@ -11,11 +11,11 @@ use anyhow::Result; use common::package::Package; -use serde::Deserialize; -use serde::Serialize; -use std::fs; -use std::path::Path; -use std::path::PathBuf; +use serde::{Deserialize, Serialize}; +use std::{ + fs, + path::{Path, PathBuf}, +}; // TODO add an option to allow fetching a tarball without decompressing it? @@ -87,7 +87,7 @@ impl Source { let (path, _) = common::util::create_tmp_file(WORK_DIR)?; let mut download_task = DownloadTask::new(url, &path).await?; // TODO progress bar - while download_task.next().await? {} + while download_task.next().await? > 0 {} // TODO check integrity with hash if specified common::util::decompress(&path, &dest_path)?; // TODO remove archive? diff --git a/builder/src/main.rs b/builder/src/main.rs index 0235a4d..8c50fc2 100644 --- a/builder/src/main.rs +++ b/builder/src/main.rs @@ -4,16 +4,13 @@ mod build; mod desc; mod util; -use crate::build::BuildProcess; -use crate::util::{get_build_triplet, get_jobs_count}; -use anyhow::Result; -use anyhow::{anyhow, bail}; -use common::repository::Repository; -use std::env; -use std::fs; -use std::path::PathBuf; -use std::process::exit; -use std::str; +use crate::{ + build::BuildProcess, + util::{get_build_triplet, get_jobs_count}, +}; +use anyhow::{anyhow, bail, Result}; +use common::{repository::Repository, serde_json}; +use std::{env, fs, io, path::PathBuf, process::exit, str}; use tokio::runtime::Runtime; /// The path to the work directory. @@ -44,6 +41,25 @@ fn print_usage(bin: &str) { eprintln!("All environment variable are optional"); } +/// Prepares the repository's directory for the package. +/// +/// On success, the function returns the output archive path. +fn prepare(build_process: &BuildProcess, to: PathBuf) -> io::Result { + // Create directory + let build_desc = build_process.get_build_desc(); + let name = &build_desc.package.name; + let version = &build_desc.package.version; + let package_path = to.join(name).join(version.to_string()); + fs::create_dir_all(&package_path)?; + // Create descriptor + let desc_path = package_path.join("desc"); + let desc = serde_json::to_string(&build_desc.package)?; + fs::write(desc_path, desc)?; + // Get archive path + let repo = Repository::load(to)?; + Ok(repo.get_archive_path(name, version)) +} + /// Builds the package. /// /// `from` and `to` correspond to the command line arguments. @@ -73,18 +89,8 @@ fn build(from: PathBuf, to: PathBuf) -> Result<()> { bail!("Package build failed!"); } println!("[INFO] Prepare repository at `{}`...", to.display()); - // TODO Move to separate function - let archive_path = { - let build_desc = build_process.get_build_desc(); - let name = build_desc.package.get_name(); - let version = build_desc.package.get_version(); - let package_path = to.join(name).join(version.to_string()); - fs::create_dir_all(&package_path)?; - let desc_path = package_path.join("desc"); - common::util::write_json(&desc_path, &build_desc.package)?; - let repo = Repository::load(to)?; - repo.get_archive_path(name, version) - }; + let archive_path = prepare(&build_process, to) + .map_err(|e| anyhow!("Failed to prepare directory for package: {e}"))?; println!("[INFO] Create archive..."); build_process .create_archive(&archive_path) diff --git a/builder/src/util.rs b/builder/src/util.rs index 2b0cf8a..757332e 100644 --- a/builder/src/util.rs +++ b/builder/src/util.rs @@ -2,10 +2,7 @@ use anyhow::{anyhow, Result}; use core::str; -use std::ffi::OsStr; -use std::num::NonZeroUsize; -use std::process::Command; -use std::{env, io, thread}; +use std::{env, ffi::OsStr, io, num::NonZeroUsize, process::Command, thread}; /// Default build triplet in case it cannot be retrieved. const DEFAULT_BUILD_TRIPLET: &str = "x86_64-linux-gnu"; diff --git a/client/Cargo.toml b/client/Cargo.toml index ef4650e..8a70b31 100644 --- a/client/Cargo.toml +++ b/client/Cargo.toml @@ -4,9 +4,7 @@ version = "0.1.0" edition = "2021" [dependencies] -anyhow = "1.0.87" common = { path = "../common" } -tokio = { version = "1.40.0", features = ["macros", "rt", "rt-multi-thread"] } [features] default = [] diff --git a/client/src/confirm.rs b/client/src/confirm.rs index 79ff638..e34947c 100644 --- a/client/src/confirm.rs +++ b/client/src/confirm.rs @@ -1,37 +1,20 @@ -//! This module implements a confirmation prompt. +//! Confirmation prompt. -use std::io; -use std::io::BufRead; -use std::io::Write; +use common::maestro_utils; /// Asks for confirmation. If yes, true is returned. Else, false is returned. pub fn prompt() -> bool { - let mut first = true; - let stdin = io::stdin(); - let mut response; - loop { - if first { - print!("Confirm? [y/n] "); - } else { - print!("Please type `y` or `n`. "); - } - - let _ = io::stdout().flush(); - - // Waiting for an input line - let input = stdin.lock().lines().next().unwrap().unwrap(); - response = input == "y"; - - // If the input is correct, stop asking - if input == "y" || input == "n" { - break; + let Some(input) = maestro_utils::prompt::prompt(Some("Confirm? [Y/n] "), false) else { + // Input closed, abort + break false; + }; + let input = input.trim().to_lowercase(); + match input.as_str() { + "" | "y" | "ye" | "yes" => break true, + "n" | "no" => break false, + // Retry + _ => {} } - - first = false; } - - println!(); - - response } diff --git a/client/src/install.rs b/client/src/install.rs index 2d77338..f6ff6fd 100644 --- a/client/src/install.rs +++ b/client/src/install.rs @@ -1,17 +1,16 @@ //! This module handles package installation. use crate::confirm; -use anyhow::bail; -use anyhow::Result; -use common::package::Package; -use common::repository; -use common::repository::Repository; -use common::Environment; -use std::collections::HashMap; -use std::path::PathBuf; - #[cfg(feature = "network")] use common::repository::remote::Remote; +use common::{ + anyhow::{bail, Result}, + package::Package, + repository, + repository::Repository, + Environment, +}; +use std::{collections::HashMap, io, path::PathBuf}; // TODO Clean /// Installs the given list of packages. @@ -23,17 +22,17 @@ use common::repository::remote::Remote; pub async fn install( names: &[String], env: &mut Environment, - local_repos: &[PathBuf], + local_repos: Vec, ) -> Result<()> { - let installed = env.load_installed_list()?; - - let mut failed = false; - // The list of repositories - let repos = env.list_repositories(local_repos)?; + let repos = local_repos + .into_iter() + .map(Repository::load) + .collect::>>()?; + // Tells whether the operation failed + let mut failed = false; // The list of packages to install with their respective repository let mut packages = HashMap::::new(); - for name in names { let pkg = repository::get_package_with_constraint(&repos, name, None)?; let Some((repo, pkg)) = pkg else { @@ -42,31 +41,28 @@ pub async fn install( continue; }; packages.insert(pkg, repo); - - if let Some(installed) = installed.get(name) { - println!( - "Package `{name}` version `{}` is already installed. Reinstalling", - installed.desc.get_version() - ); + // If already installed, print message + if let Some(version) = env.get_installed_version(name) { + println!("Package `{name}` version `{version}` is already installed. Reinstalling",); } } if failed { bail!("installation failed"); } - println!("Resolving dependencies..."); - // The list of all packages, dependencies included let mut total_packages = packages.clone(); - // TODO check dependencies for all packages at once to avoid duplicate errors // Resolving dependencies for (package, _) in packages { let res = package.resolve_dependencies( &mut total_packages, &mut |name, version_constraint| { - let res = - repository::get_package_with_constraint(&repos, name, Some(version_constraint)); + let res = repository::get_package_with_constraint( + &repos, + name, + Some(version_constraint), + ); let pkg = match res { Ok(p) => p, Err(e) => { @@ -74,14 +70,11 @@ pub async fn install( return None; } }; - match pkg { Some((repo, pkg)) => Some((pkg, repo)), - // If not present, check on remote None => { - // TODO - todo!(); + todo!() } } }, @@ -90,113 +83,98 @@ pub async fn install( for e in errs { eprintln!("{e}"); } - failed = true; } } if failed { bail!("installation failed"); } - println!("Packages to be installed:"); - // List packages to be installed #[cfg(feature = "network")] { let mut total_size = 0; for (pkg, repo) in &total_packages { - let name = pkg.get_name(); - let version = pkg.get_version(); - + let name = &pkg.name; + let version = &pkg.version; match repo.get_package(name, version)? { Some(_) => println!("\t- {name} ({version}) - cached"), - None => { - let remote = repo.get_remote().unwrap(); - // Get package size from remote + let remote = repo.get_remote().unwrap(); let size = remote.get_size(pkg).await?; total_size += size; - println!("\t- {name} ({version}) - download size: {size}"); } } } - - print!("Total download size: "); - common::util::print_size(total_size); - println!(); + println!( + "Total download size: {}", + common::maestro_utils::util::ByteSize(total_size) + ); } #[cfg(not(feature = "network"))] { for pkg in total_packages.keys() { - println!("\t- {} ({}) - cached", pkg.get_name(), pkg.get_version()); + println!("\t- {} ({}) - cached", pkg.name, pkg.version); } } - if !confirm::prompt() { println!("Aborting."); return Ok(()); } - #[cfg(feature = "network")] { println!("Downloading packages..."); let mut futures = Vec::new(); - // TODO download biggest packages first (sort_unstable by decreasing size) for (pkg, repo) in &total_packages { - if repo.is_in_cache(pkg.get_name(), pkg.get_version()) { - println!("`{}` is in cache.", pkg.get_name()); + if repo.is_in_cache(&pkg.name, &pkg.version) { + println!("`{}` is in cache.", &pkg.name); continue; } - if let Some(remote) = repo.get_remote() { // TODO limit the number of packages downloaded concurrently futures.push(( - pkg.get_name(), - pkg.get_version(), + &pkg.name, + &pkg.version, // TODO spawn task async { let mut task = Remote::fetch_archive(remote, repo, pkg).await?; - while task.next().await? { + while task.next().await? > 0 { // TODO update progress bar } - - Ok::<(), anyhow::Error>(()) + Ok::<(), common::anyhow::Error>(()) }, )); } } - // TODO Add progress bar for (name, version, f) in futures { match f.await { Ok(()) => continue, - Err(e) => eprintln!("Failed to download `{name}` version `{version}`: {e}"), + Err(error) => { + eprintln!("Failed to download `{name}` version `{version}`: {error}") + } } } if failed { bail!("installation failed"); } } - println!(); println!("Installing packages..."); - - // Installing all packages + // Install all packages for (pkg, repo) in total_packages { - println!("Installing `{}`...", pkg.get_name()); - - let archive_path = repo.get_archive_path(pkg.get_name(), pkg.get_version()); + println!("Installing `{}`...", pkg.name); + let archive_path = repo.get_archive_path(&pkg.name, &pkg.version); if let Err(e) = env.install(&pkg, &archive_path) { - eprintln!("Failed to install `{}`: {e}", pkg.get_name()); + eprintln!("Failed to install `{}`: {e}", &pkg.name); failed = true; } } if failed { bail!("installation failed"); } - Ok(()) } diff --git a/client/src/main.rs b/client/src/main.rs index 9492833..c2a7985 100644 --- a/client/src/main.rs +++ b/client/src/main.rs @@ -2,52 +2,58 @@ mod confirm; mod install; +#[cfg(feature = "network")] +mod remote; mod remove; - #[cfg(feature = "network")] mod update; -use anyhow::anyhow; -use anyhow::Result; -use common::Environment; +use common::{ + anyhow::{anyhow, Result}, + tokio, Environment, +}; use install::install; use remove::remove; -use std::env; -use std::path::{Path, PathBuf}; -use std::process::exit; -use tokio::runtime::Runtime; - -#[cfg(feature = "network")] -use common::repository::remote::Remote; +use std::{ + env, + path::{Path, PathBuf}, + process::exit, +}; /// Prints command line usage. -fn print_usage(bin: &str) { +fn print_usage() { eprintln!( "blimp package manager version {}", env!("CARGO_PKG_VERSION") ); eprintln!(); eprintln!("USAGE:"); - eprintln!("\t{} [OPTIONS]", bin); + eprintln!("\tblimp [OPTIONS]"); eprintln!(); eprintln!("COMMAND:"); eprintln!("\tinfo : Prints information about the given package(s)"); eprintln!("\tinstall : Installs the given package(s)"); - eprintln!("\tupdate: Synchronizes packets information from remote"); + #[cfg(feature = "network")] + { + eprintln!("\tupdate: Synchronizes packets information from remote"); + } eprintln!( "\tupgrade [package...]: Upgrades the given package(s). If no package is specified, \ -the package manager updates every packages that are not up to date" +the package manager updates every package that is not up to date" ); eprintln!("\tremove : Removes the given package(s)"); eprintln!("\tclean: Clean the cache"); - eprintln!("\tremote-list: Lists remote servers"); - eprintln!("\tremote-add : Adds a remote server"); - eprintln!("\tremote-remove : Removes a remote server"); + #[cfg(feature = "network")] + { + eprintln!("\tremote-list: Lists remote servers"); + eprintln!("\tremote-add : Adds a remote server"); + eprintln!("\tremote-remove : Removes a remote server"); + } eprintln!(); eprintln!("OPTIONS:"); eprintln!("\t--verbose: Enables verbose mode"); eprintln!( - "\t--version : When installing or upgrading, this option allows to\ + "\t--version : When installing or upgrading, this option allows to \ specify a version" ); eprintln!(); @@ -55,16 +61,10 @@ specify a version" eprintln!("\tSYSROOT: Specifies the path to the system's root"); eprintln!( "\tLOCAL_REPO: Specifies paths separated by `:` at which packages are \ -stored locally (the SYSROOT variable doesn't apply to these paths)" +stored locally (the SYSROOT variable does not apply to these paths)" ); } -/// Prints the message to tell that the required feature is not available. -#[allow(unused)] -fn network_not_enabled() { - eprintln!("This feature is not enabled. To use it, recompile with the feature `network`"); -} - /// Returns an environment for the given sysroot. /// /// If the environment's lockfile cannot be acquired, the function returns an error. @@ -72,81 +72,14 @@ fn get_env(sysroot: &Path) -> Result { Environment::with_root(sysroot)?.ok_or(anyhow!("failed to acquire lockfile")) } -/// Lists remotes. -#[cfg(feature = "network")] -fn remote_list(env: &Environment) -> std::io::Result<()> { - let remotes = Remote::load_list(env)?; - - println!("Remotes list:"); - - for r in remotes { - let host = r.get_host(); - - match r.get_motd() { - Ok(m) => println!("- {} (status: UP): {}", host, m), - Err(_) => println!("- {} (status: DOWN)", host), - } - } - - Ok(()) -} - -/// Adds one or several remotes. -/// -/// Arguments: -/// - `env` is the environment. -/// - `remotes` is the list of remotes to add. -#[cfg(feature = "network")] -fn remote_add(env: &mut Environment, remotes: &[String]) -> std::io::Result<()> { - let mut list = Remote::load_list(env)?; - list.sort(); - - for r in remotes { - match list.binary_search_by(|r1| r1.get_host().cmp(r)) { - Ok(_) => eprintln!("Remote `{}` already exists", r), - Err(_) => list.push(Remote::new(r.clone())), - } - } - - Remote::save_list(env, &list)?; - Ok(()) -} - -/// Removes one or several remotes. -/// -/// Arguments: -/// - `env` is the environment. -/// - `remotes` is the list of remotes to remove. -#[cfg(feature = "network")] -fn remote_remove(env: &mut Environment, remotes: &[String]) -> std::io::Result<()> { - let mut list = Remote::load_list(env)?; - list.sort(); - - for r in remotes { - match list.binary_search_by(|r1| r1.get_host().cmp(r)) { - Ok(i) => { - let _ = list.remove(i); - } - Err(_) => eprintln!("Remote `{}` not found", r), - } - } - - Remote::save_list(env, &list)?; - Ok(()) -} - -fn main_(sysroot: &Path, local_repos: &[PathBuf]) -> Result { - let args: Vec = env::args().collect(); - // Name of the current binary file - let bin = args.first().map(|s| s.as_str()).unwrap_or("blimp"); - +async fn main_impl(sysroot: &Path, local_repos: Vec) -> Result { // If no argument is specified, print usage + let args: Vec = env::args().collect(); if args.len() <= 1 { - print_usage(bin); + print_usage(); return Ok(false); } - - // Matching command + // Match command match args[1].as_str() { "info" => { let packages = &args[2..]; @@ -154,73 +87,53 @@ fn main_(sysroot: &Path, local_repos: &[PathBuf]) -> Result { eprintln!("Please specify one or several packages"); return Ok(false); } - - // TODO - todo!(); + todo!() } - #[cfg(feature = "network")] "update" => { let mut env = get_env(sysroot)?; - let rt = Runtime::new()?; - rt.block_on(update::update(&mut env))?; - + update::update(&mut env).await?; Ok(true) } - "install" => { let names = &args[2..]; if names.is_empty() { eprintln!("Please specify one or several packages"); return Ok(false); } - let mut env = get_env(sysroot)?; - let rt = Runtime::new()?; - rt.block_on(install(names, &mut env, local_repos))?; - + install(names, &mut env, local_repos).await?; Ok(true) } - "upgrade" => { let names = &args[2..]; if names.is_empty() { eprintln!("Please specify one or several packages"); return Ok(false); } - let _env = get_env(sysroot)?; - // TODO - todo!(); + todo!() } - "remove" => { let names = &args[2..]; if names.is_empty() { eprintln!("Please specify one or several packages"); return Ok(false); } - let mut env = get_env(sysroot)?; remove(names, &mut env)?; - Ok(true) } - "clean" => { let _env = get_env(sysroot)?; - // TODO - todo!(); + todo!() } - #[cfg(feature = "network")] "remote-list" => { let env = get_env(sysroot)?; - remote_list(&env)?; - + remote::list(&env).await?; Ok(true) } - #[cfg(feature = "network")] "remote-add" => { let names = &args[2..]; @@ -228,13 +141,10 @@ fn main_(sysroot: &Path, local_repos: &[PathBuf]) -> Result { eprintln!("Please specify one or several remotes to add"); return Ok(false); } - let mut env = get_env(sysroot)?; - remote_add(&mut env, names)?; - + remote::add(&mut env, names)?; Ok(true) } - #[cfg(feature = "network")] "remote-remove" => { let names = &args[2..]; @@ -242,45 +152,41 @@ fn main_(sysroot: &Path, local_repos: &[PathBuf]) -> Result { eprintln!("Please specify one or several remotes to remove"); return Ok(false); } - let mut env = get_env(sysroot)?; - remote_remove(&mut env, names)?; - + remote::remove(&mut env, names)?; Ok(true) } - #[cfg(not(feature = "network"))] "update" | "remote-list" | "remote-add" | "remote-remove" => { - network_not_enabled(); + eprintln!( + "This feature is not enabled. To use it, recompile the package manager with the feature `network`" + ); Ok(false) } - - _ => { - eprintln!("Command `{}` doesn't exist", args[1]); + cmd => { + eprintln!("Command `{cmd}` does not exist"); eprintln!(); - print_usage(bin); - + print_usage(); Ok(false) } } } -fn main() { +#[tokio::main] +async fn main() { let sysroot = env::var_os("SYSROOT") .map(PathBuf::from) .unwrap_or(PathBuf::from("/")); - let local_repos: Vec = env::var("LOCAL_REPO") // TODO var_os + let local_repos = env::var("LOCAL_REPO") // TODO var_os .map(|s| s.split(':').map(PathBuf::from).collect()) .unwrap_or_default(); - - match main_(&sysroot, &local_repos) { + let res = main_impl(&sysroot, local_repos).await; + match res { Ok(false) => exit(1), - Err(e) => { eprintln!("error: {e}"); exit(1); } - _ => {} } } diff --git a/client/src/remote.rs b/client/src/remote.rs new file mode 100644 index 0000000..2752ca6 --- /dev/null +++ b/client/src/remote.rs @@ -0,0 +1,55 @@ +//! Remotes management. + +use common::{repository::remote::Remote, Environment}; + +/// Lists remotes. +pub async fn list(env: &Environment) -> std::io::Result<()> { + let remotes = Remote::load_list(env)?; + println!("Remotes list:"); + for remote in remotes { + let host = &remote.host; + match remote.fetch_motd().await { + Ok(motd) => println!("- {host} (status: UP): {motd}"), + Err(_) => println!("- {host} (status: DOWN)"), + } + } + Ok(()) +} + +/// Adds one or several remotes. +/// +/// Arguments: +/// - `env` is the environment. +/// - `remotes` is the list of remotes to add. +pub fn add(env: &mut Environment, new_remotes: &[String]) -> std::io::Result<()> { + let mut remotes = Remote::load_list(env)?; + for remote in new_remotes { + if remotes.contains(remote.as_str()) { + eprintln!("Remote `{remote}` already exists"); + } else { + println!("Add remote `{remote}`"); + remotes.insert(Remote { + host: remote.clone(), + }); + } + } + Remote::save_list(env, remotes.into_iter())?; + Ok(()) +} + +/// Removes one or several remotes. +/// +/// Arguments: +/// - `env` is the environment. +/// - `remotes` is the list of remotes to remove. +pub fn remove(env: &mut Environment, new_remotes: &[String]) -> std::io::Result<()> { + let mut remotes = Remote::load_list(env)?; + for remote in new_remotes { + let existed = remotes.remove(remote.as_str()); + if !existed { + eprintln!("Remote `{remote}` not found"); + } + } + Remote::save_list(env, remotes.into_iter())?; + Ok(()) +} diff --git a/client/src/remove.rs b/client/src/remove.rs index 7f0f6ea..51295ea 100644 --- a/client/src/remove.rs +++ b/client/src/remove.rs @@ -1,10 +1,6 @@ //! TODO doc -use anyhow::anyhow; -use anyhow::bail; -use anyhow::Result; -use common::package; -use common::Environment; +use common::{anyhow::Result, Environment}; // TODO ask for confirm before remove @@ -13,52 +9,6 @@ use common::Environment; /// Arguments: /// - `names` is the list of packages to remove. /// - `env` is the blimp environment. -pub fn remove(names: &[String], env: &mut Environment) -> Result<()> { - let installed = env.load_installed_list()?; - - // The list of remaining packages after the remove operation - let remaining = { - let mut installed = installed.clone(); - installed.retain(|name, _| !names.contains(name)); - - installed - }; - - // Check for dependency breakages - let unmatched_deps = package::list_unmatched_dependencies(&remaining); - if !unmatched_deps.is_empty() { - eprintln!("The following dependencies would be broken:"); - - for (pkg, dep) in unmatched_deps { - eprintln!( - "- for package `{}` (version `{}`): {}", - pkg.desc.get_name(), - pkg.desc.get_version(), - dep - ); - } - - bail!("dependencies would break"); - } - - let mut failed = false; - // Remove packages - for name in names { - if let Some(installed) = installed.get(name) { - env.remove(installed).map_err(|e| { - anyhow!( - "failed to remove package `{}`: {e}", - installed.desc.get_name() - ) - })?; - } else { - eprintln!("Package `{}` not found!", name); - failed = true; - } - } - if failed { - bail!("cannot remove packages"); - } - - Ok(()) +pub fn remove(_names: &[String], _env: &mut Environment) -> Result<()> { + todo!() } diff --git a/client/src/update.rs b/client/src/update.rs index 0fdbba9..2afed2a 100644 --- a/client/src/update.rs +++ b/client/src/update.rs @@ -1,44 +1,35 @@ //! This module handles packages list updating. -use anyhow::anyhow; -use anyhow::Result; -use common::repository::remote::Remote; -use common::Environment; +use common::{ + anyhow::{anyhow, bail, Result}, + repository::remote::Remote, + Environment, +}; /// Updates the packages list. pub async fn update(env: &mut Environment) -> Result<()> { - let remotes = - Remote::load_list(env).map_err(|e| anyhow!("Could not update packages list: {}", e))?; - + let remotes = Remote::load_list(env) + .map_err(|error| anyhow!("Could not update packages list: {error}"))?; println!("Updating from remotes..."); - let mut futures = Vec::new(); - for r in remotes { - let host = r.get_host().to_owned(); - // TODO limit the number of concurrent tasks running - futures.push((host, tokio::spawn(async move { r.fetch_list().await }))); + for r in &remotes { + futures.push((&r.host, r.fetch_list())); } - - let mut err = false; + let mut failed = false; for (host, f) in futures { - match f.await? { + match f.await { Ok(packages) => { println!("Remote `{host}`: Found {} package(s).", packages.len()); - - // TODO - todo!(); + todo!() } - Err(e) => { eprintln!("Remote `{host}`: {e}"); - err = true; + failed = true; } } } - - if err { - Err(anyhow!("update failed")) - } else { - Ok(()) + if failed { + bail!("update failed"); } + Ok(()) } diff --git a/common/Cargo.toml b/common/Cargo.toml index 99cca0a..64a7dac 100644 --- a/common/Cargo.toml +++ b/common/Cargo.toml @@ -7,19 +7,21 @@ edition = "2021" path = "src/lib.rs" [dependencies] -anyhow = "1.0.87" -bytes = "1.7.1" +anyhow = "1.0.93" +bytes = "1.8.0" bzip2 = "0.4.4" -flate2 = "1.0.33" -futures = "0.3.30" -futures-util = "0.3.30" +flate2 = "1.0.34" +futures = "0.3.31" +futures-util = "0.3.31" infer = "0.16.0" rand = "0.8.5" -reqwest = { version = "0.12.7", features = ["blocking", "json", "stream"], optional = true } -serde = { version = "1.0.210", features = ["derive"] } -serde_json = "1.0.128" -tar = "0.4.41" -tokio = { version = "1.40.0", features = ["rt", "rt-multi-thread"] } +reqwest = { version = "0.12.9", features = ["json", "stream"], optional = true } +serde = { version = "1.0.214", features = ["derive"] } +serde_json = "1.0.132" +tar = "0.4.43" +tokio = { version = "1.41.1", features = ["fs", "macros", "rt", "rt-multi-thread"] } +tokio-util = { version = "0.7.12", features = ["io"] } +utils = { git = "https://github.com/maestro-os/maestro-utils" } xz2 = "0.1.7" [features] diff --git a/common/src/download.rs b/common/src/download.rs index 946f728..00f6709 100644 --- a/common/src/download.rs +++ b/common/src/download.rs @@ -2,28 +2,25 @@ use anyhow::Result; use bytes::Bytes; -use futures_util::stream::Stream; -use futures_util::stream::StreamExt; -use std::fs::File; -use std::fs::OpenOptions; -use std::io::Write; -use std::path::Path; -use std::pin::Pin; +use futures_util::stream::{Stream, StreamExt}; +use std::{ + fs::{File, OpenOptions}, + io::Write, + path::Path, + pin::Pin, +}; /// A download task, running until the file has been downloaded entirely. pub struct DownloadTask { /// The response byte stream. stream: Pin> + Send>>, - /// The total size to be downloaded in bytes. If unknown, the value is None. - total_size: Option, - /// The destination file. file: File, + + /// The total size to be downloaded in bytes. If unknown, the value is None. + total_size: Option, /// The current downloaded size in bytes. curr_size: u64, - - /// Tells whether the task is running. If `false`, downloading is over. - running: bool, } impl DownloadTask { @@ -34,23 +31,17 @@ impl DownloadTask { /// - `path` is the path to which the file has to be saved. pub async fn new(url: &str, path: &Path) -> Result { let response = reqwest::get(url).await?; - let total_size = response.content_length(); - let stream = response.bytes_stream(); - let file = OpenOptions::new() .create(true) .write(true) .truncate(true) .open(path)?; - + let total_size = response.content_length(); Ok(Self { - stream: Box::pin(stream), - total_size, - + stream: Box::pin(response.bytes_stream()), file, + total_size, curr_size: 0, - - running: true, }) } @@ -64,22 +55,16 @@ impl DownloadTask { self.curr_size } - /// Pulls the next chunk of data. - /// - /// If the task is over, the function returns `false`. - pub async fn next(&mut self) -> Result { - let mut running = true; - + /// Pulls the next chunk of data and returns the number of bytes downloaded. + pub async fn next(&mut self) -> Result { if let Some(chunk) = self.stream.next().await { let chunk = chunk?; self.curr_size += chunk.len() as u64; self.file.write_all(&chunk)?; + Ok(chunk.len()) } else { - running = false; - }; - - self.running = running; - Ok(self.running) + Ok(0) + } } } diff --git a/common/src/lib.rs b/common/src/lib.rs index af45834..68309d6 100644 --- a/common/src/lib.rs +++ b/common/src/lib.rs @@ -2,33 +2,36 @@ #![feature(io_error_more)] +pub use anyhow; +pub use serde_json; +pub use tokio; +pub use tokio_util; +pub use utils as maestro_utils; + +#[cfg(feature = "network")] +pub mod download; pub mod lockfile; pub mod package; pub mod repository; pub mod util; pub mod version; -#[cfg(feature = "network")] -pub mod download; - +use crate::version::Version; use anyhow::Result; -use package::InstalledPackage; -use package::Package; -use repository::Repository; -use std::collections::HashMap; -use std::error::Error; -use std::fs; -use std::io; -use std::io::ErrorKind; -use std::path::Path; -use std::path::PathBuf; +use package::{InstalledPackage, Package}; +use std::{ + error::Error, + fs, io, + io::ErrorKind, + path::{Path, PathBuf}, +}; /// The directory containing cached packages. -const LOCKFILE_PATH: &str = "/usr/lib/blimp/.lock"; -/// The path to the file storing the list of installed packages. -const INSTALLED_FILE: &str = "/usr/lib/blimp/installed"; +const LOCKFILE_PATH: &str = "var/lib/blimp/.lock"; +/// The path to directory storing information about installed packages. +const INSTALLED_DB: &str = "var/lib/blimp/installed"; -/// An instance of a Blimp environment. +/// An environment is a system managed by the package manager. /// /// On creation, the environment creates a lockfile to ensure no other instance can access it at /// the same time. @@ -46,7 +49,7 @@ impl Environment { /// same time. If already locked, the function returns `None`. pub fn with_root(sysroot: &Path) -> io::Result> { let sysroot = sysroot.canonicalize()?; - let path = util::concat_paths(&sysroot, LOCKFILE_PATH); + let path = sysroot.join(LOCKFILE_PATH); let acquired = lockfile::lock(&path)?; Ok(acquired.then_some(Self { sysroot, @@ -54,40 +57,13 @@ impl Environment { } /// Returns the sysroot of the current environment. - pub fn get_sysroot(&self) -> &Path { + pub fn sysroot(&self) -> &Path { &self.sysroot } - /// Loads and returns the list of all repositories. - /// - /// `local_repos` is the list of paths to local repositories. - pub fn list_repositories(&self, local_repos: &[PathBuf]) -> io::Result> { - // TODO Add blimp's inner repositories (local representations of remotes) - local_repos - .iter() - .map(|path| Repository::load(path.clone())) - .collect::, _>>() - } - - /// Loads the list of installed packages. - /// - /// The key is the name of the package and the value is the installed package. - pub fn load_installed_list(&self) -> io::Result> { - let path = util::concat_paths(&self.sysroot, INSTALLED_FILE); - match util::read_json::>(&path) { - Ok(pkgs) => Ok(pkgs), - Err(e) if e.kind() == ErrorKind::NotFound => Ok(HashMap::new()), - Err(e) => Err(e), - } - } - - /// Updates the list of installed packages to the disk. - pub fn update_installed_list( - &self, - list: &HashMap, - ) -> io::Result<()> { - let path = util::concat_paths(&self.sysroot, INSTALLED_FILE); - util::write_json(&path, list) + /// Returns the installed version for the package with the given `name`. + pub fn get_installed_version(&self, _name: &str) -> Option { + todo!() } /// Installs the given package. @@ -98,7 +74,7 @@ impl Environment { /// /// The function does not resolve dependencies. It is the caller's responsibility to install /// them beforehand. - pub fn install(&self, pkg: &Package, archive_path: &Path) -> Result<(), Box> { + pub fn install(&self, _pkg: &Package, archive_path: &Path) -> Result<(), Box> { // Read archive let mut archive = util::read_package_archive(archive_path)?; // TODO Get hooks (pre-install-hook and post-install-hook) @@ -123,16 +99,7 @@ impl Environment { files.push(path); } // TODO Execute post-install-hook - // Update installed list - let mut installed = self.load_installed_list()?; - installed.insert( - pkg.get_name().to_owned(), - InstalledPackage { - desc: pkg.clone(), - files, - }, - ); - self.update_installed_list(&installed)?; + // TODO add package to installed db Ok(()) } @@ -141,25 +108,14 @@ impl Environment { /// Arguments: /// - `pkg` is the package to be updated. /// - `archive_path` is the path to the archive of the new version of the package. - pub fn update(&self, pkg: &Package, archive_path: &Path) -> Result<()> { + pub fn update(&self, _pkg: &Package, archive_path: &Path) -> Result<()> { // Read archive let _archive = util::read_package_archive(archive_path)?; // TODO Get hooks (pre-update-hook and post-update-hook) // TODO Execute pre-update-hook - // The list of installed files - let files = vec![]; // TODO Patch files corresponding to the ones in inner data archive // TODO Execute post-update-hook - // Update installed list - let mut installed = self.load_installed_list()?; - installed.insert( - pkg.get_name().to_owned(), - InstalledPackage { - desc: pkg.clone(), - files, - }, - ); - self.update_installed_list(&installed)?; + // TODO update package in installed db Ok(()) } @@ -192,17 +148,14 @@ impl Environment { } } // TODO Execute post-remove-hook - // Update installed list - let mut installed = self.load_installed_list()?; - installed.remove(pkg.desc.get_name()); - self.update_installed_list(&installed)?; + // TODO remove package from installed db Ok(()) } } impl Drop for Environment { fn drop(&mut self) { - let path = util::concat_paths(&self.sysroot, LOCKFILE_PATH); + let path = self.sysroot.join(LOCKFILE_PATH); lockfile::unlock(&path).unwrap_or_else(|e| eprintln!("blimp: could remove lockfile: {e}")); } } diff --git a/common/src/lockfile.rs b/common/src/lockfile.rs index 44d5f1b..762a771 100644 --- a/common/src/lockfile.rs +++ b/common/src/lockfile.rs @@ -1,10 +1,7 @@ //! The lock file allows to prevent several instances of the package manager from running at the //! same time. -use std::fs; -use std::fs::OpenOptions; -use std::io; -use std::path::Path; +use std::{fs, fs::OpenOptions, io, path::Path}; /// Creates the lock file if not present. /// @@ -15,7 +12,8 @@ pub fn lock(path: &Path) -> io::Result { if let Some(parent) = path.parent() { fs::create_dir_all(parent)?; } - // Trying to create the file and failing if it already exists, preventing TOCTOU race conditions + // Try to create the file and failing if it already exists, preventing TOCTOU race + // conditions let acquired = OpenOptions::new() .write(true) .create_new(true) diff --git a/common/src/package.rs b/common/src/package.rs index d599b7a..97a2270 100644 --- a/common/src/package.rs +++ b/common/src/package.rs @@ -1,26 +1,20 @@ //! A package is a software that can be installed using the package manager. -//! Packages are usualy downloaded from a remote host. - -use crate::repository::Repository; -use crate::version::Version; -use crate::version::VersionConstraint; -use serde::Deserialize; -use serde::Serialize; -use std::collections::HashMap; -use std::fmt; -use std::fmt::Display; -use std::fmt::Formatter; -use std::fs; -use std::io; -use std::io::ErrorKind; -use std::path::PathBuf; - -/// The directory storing packages' descriptions on the serverside. -pub const SERVER_PACKAGES_DESC_DIR: &str = "public_desc"; -/// The directory storing packages' archives on the serverside. -pub const SERVER_PACKAGES_DIR: &str = "public_packages"; +//! +//! Packages are usually downloaded from a remote host. + +use crate::{ + repository::Repository, + version::{Version, VersionConstraint}, +}; +use serde::{Deserialize, Serialize}; +use std::{collections::HashMap, fmt, fs, io, io::ErrorKind, path::PathBuf}; + +/// Tells whether the given package name is valid. +pub fn is_valid_name(name: &str) -> bool { + name.chars().all(|c| c.is_ascii_alphanumeric() || c == '-') +} -/// Enumeration of possible package dependencies resolution error. +/// Enumeration of package dependency resolution errors. pub enum ResolveError { /// The dependency cannot be found. NotFound { @@ -29,7 +23,6 @@ pub enum ResolveError { /// The version constraints on the dependency. version_constraint: VersionConstraint, }, - /// The dependency version conflicts another package or dependency. VersionConflict { /// The name of the dependency. @@ -54,10 +47,8 @@ impl fmt::Display for ResolveError { "Unresolved dependency `{name}` for constraint `{version_constraint}`" )?; } - Self::VersionConflict { name, - required_version, other_version, } => { @@ -67,38 +58,24 @@ impl fmt::Display for ResolveError { )?; } } - Ok(()) } } -/// Structure representing a package dependency. +/// A package dependency. #[derive(Clone, Deserialize, Eq, Hash, PartialEq, Serialize)] pub struct Dependency { /// The dependency's name. - name: String, - + pub name: String, /// The dependency's version constraints. /// /// The version of the package must match the intersection of all the constraints. #[serde(rename = "version")] - version_constraint: VersionConstraint, -} - -impl Dependency { - /// Returns the name of the package. - pub fn get_name(&self) -> &String { - &self.name - } - - /// Returns the version of the package. - pub fn get_version_constraint(&self) -> &VersionConstraint { - &self.version_constraint - } + pub version_constraint: VersionConstraint, } -impl Display for Dependency { - fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { +impl fmt::Display for Dependency { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!(f, "{}: {}", self.name, self.version_constraint) } } @@ -107,23 +84,22 @@ impl Display for Dependency { #[derive(Clone, Deserialize, Eq, Hash, PartialEq, Serialize)] pub struct Package { /// The package's name. - name: String, + pub name: String, /// The package's version. - version: Version, - + pub version: Version, /// The package's description. - description: String, + pub description: String, /// Dependencies required to build the package. - build_deps: Vec, + pub build_deps: Vec, /// Dependencies required to run the package. - run_deps: Vec, + pub run_deps: Vec, } impl Package { /// Loads a package from the given path. /// - /// If the package doesn't exist, the function returns None. + /// If the package does not exist, the function returns None. pub fn load(path: PathBuf) -> io::Result> { match fs::read_to_string(path.join("desc")) { Ok(content) => Ok(Some(serde_json::from_str(&content)?)), @@ -132,31 +108,6 @@ impl Package { } } - /// Returns the name of the package. - pub fn get_name(&self) -> &str { - &self.name - } - - /// Returns the version of the package. - pub fn get_version(&self) -> &Version { - &self.version - } - - /// Returns the description of the package. - pub fn get_description(&self) -> &str { - &self.description - } - - /// Returns the list of build dependencies. - pub fn get_build_deps(&self) -> &Vec { - &self.build_deps - } - - /// Returns the list of run dependencies. - pub fn get_run_deps(&self) -> &Vec { - &self.run_deps - } - /// Resolves the dependencies of the package and inserts them into the given `HashMap`. /// /// Arguments: @@ -181,18 +132,15 @@ impl Package { for d in &self.run_deps { // TODO check already installed packages // Get package in the installation list - let pkg = packages - .iter() - .map(|(p, _)| p) - .find(|p| p.get_name() == d.get_name()); + let pkg = packages.iter().map(|(p, _)| p).find(|p| p.name == d.name); // Check for conflict if let Some(pkg) = pkg { - if !d.get_version_constraint().is_valid(pkg.get_version()) { + if !d.version_constraint.is_valid(&pkg.version) { errors.push(ResolveError::VersionConflict { - name: d.get_name().clone(), + name: d.name.clone(), - required_version: d.get_version_constraint().clone(), - other_version: pkg.get_version().clone(), + required_version: d.version_constraint.clone(), + other_version: pkg.version.clone(), }); } @@ -200,7 +148,7 @@ impl Package { } // Resolve package, then resolve its dependencies - if let Some((p, repo)) = f(d.get_name(), d.get_version_constraint()) { + if let Some((p, repo)) = f(&d.name, &d.version_constraint) { // TODO Check for dependency cycles // FIXME Possible stack overflow let res = p.resolve_dependencies(packages, f)?; @@ -211,8 +159,8 @@ impl Package { packages.insert(p, repo); } else { errors.push(ResolveError::NotFound { - name: d.get_name().clone(), - version_constraint: d.get_version_constraint().clone(), + name: d.name.clone(), + version_constraint: d.version_constraint.clone(), }); } } @@ -242,15 +190,12 @@ pub fn list_unmatched_dependencies( pkgs.iter() .flat_map(|(_, pkg)| { pkg.desc - .get_run_deps() + .run_deps .iter() .filter(|dep| { - let matching = pkgs - .get(dep.get_name()) - .map(|p| dep.get_version_constraint().is_valid(p.desc.get_version())) - .unwrap_or(false); - - !matching + pkgs.get(&dep.name) + .map(|p| dep.version_constraint.is_valid(&p.desc.version)) + .unwrap_or(false) }) .map(move |dep| (pkg, dep)) }) diff --git a/common/src/repository/mod.rs b/common/src/repository/mod.rs index 976d8f8..cbe9ebc 100644 --- a/common/src/repository/mod.rs +++ b/common/src/repository/mod.rs @@ -5,15 +5,13 @@ #[cfg(feature = "network")] pub mod remote; -use crate::package::Package; -use crate::version::Version; -use crate::version::VersionConstraint; -use std::fs; -use std::io; -use std::path::PathBuf; - +use crate::{ + package::Package, + version::{Version, VersionConstraint}, +}; #[cfg(feature = "network")] use remote::Remote; +use std::{fs, io, path::PathBuf}; /// Structure representing a local repository. pub struct Repository { @@ -110,7 +108,7 @@ impl Repository { /// Arguments: /// - `name` is the name of the package. /// - `version_constraint` is the version constraint to match. If no constraint is specified, - /// the latest version is selected. + /// the latest version is selected. /// /// If the package doesn't exist, the function returns `None`. pub fn get_package_with_constraint( @@ -171,8 +169,8 @@ pub fn get_package<'a>( /// /// Arguments: /// - `name` is the name of the package. -/// - `version_constraint` is the version constraint to match. If no constraint is specified, -/// the latest version is selected. +/// - `version_constraint` is the version constraint to match. If no constraint is specified, the +/// latest version is selected. /// /// If the package doesn't exist, the function returns `None`. pub fn get_package_with_constraint<'a>( @@ -188,5 +186,5 @@ pub fn get_package_with_constraint<'a>( _ => None, }, ) - .max_by(|(_, p0), (_, p1)| p0.get_version().cmp(p1.get_version()))) + .max_by(|(_, p0), (_, p1)| p0.version.cmp(&p1.version))) } diff --git a/common/src/repository/remote.rs b/common/src/repository/remote.rs index f185614..005f334 100644 --- a/common/src/repository/remote.rs +++ b/common/src/repository/remote.rs @@ -1,54 +1,51 @@ //! A remote is a remote host from which packages can be downloaded. -use crate::download::DownloadTask; -use crate::package::Package; -use crate::repository::Repository; -use crate::Environment; -use anyhow::anyhow; -use anyhow::Result; -use std::fs::File; -use std::fs::OpenOptions; -use std::io; -use std::io::BufRead; -use std::io::BufReader; -use std::io::BufWriter; -use std::io::Write; - -// TODO Use https +use crate::{download::DownloadTask, package::Package, repository::Repository, Environment}; +use anyhow::{anyhow, bail, Result}; +use reqwest::StatusCode; +use std::{ + borrow::Borrow, + collections::HashSet, + fs::{File, OpenOptions}, + io, + io::{BufRead, BufReader, BufWriter, Write}, +}; /// The file which contains the list of remotes. -const REMOTES_FILE: &str = "/usr/lib/blimp/remotes_list"; +const REMOTES_FILE: &str = "var/lib/blimp/remotes_list"; -/// Structure representing a remote host. -#[derive(Clone, Eq, Ord, PartialEq, PartialOrd)] +/// A remote host. +#[derive(Clone, Eq, Hash, Ord, PartialEq, PartialOrd)] pub struct Remote { /// The host's address and port (optional). - host: String, + pub host: String, } -impl Remote { - /// Creates a new instance. - pub fn new(host: String) -> Self { - Self { - host, - } +impl Borrow for Remote { + fn borrow(&self) -> &str { + &self.host } +} +impl Remote { /// Loads and returns the list of remote hosts. - pub fn load_list(env: &Environment) -> io::Result> { - let path = env.get_sysroot().join(REMOTES_FILE); + pub fn load_list(env: &Environment) -> io::Result> { + let path = env.sysroot().join(REMOTES_FILE); let file = File::open(path)?; let reader = BufReader::new(file); - reader .lines() - .map(|s| Ok(Self::new(s?))) - .collect::>>() + .map(|host| { + host.map(|host| Self { + host, + }) + }) + .collect() } /// Saves the list of remote hosts. - pub fn save_list(env: &Environment, remotes: &[Self]) -> io::Result<()> { - let path = env.get_sysroot().join(REMOTES_FILE); + pub fn save_list(env: &Environment, remotes: impl Iterator) -> io::Result<()> { + let path = env.sysroot().join(REMOTES_FILE); let file = OpenOptions::new() .read(true) .write(true) @@ -57,63 +54,45 @@ impl Remote { .open(path)?; let mut writer = BufWriter::new(file); for r in remotes { - writer.write_all(r.get_host().as_bytes())?; + writer.write_all(r.host.as_bytes())?; writer.write_all(b"\n")?; } - Ok(()) } - /// Returns the host for the remote. - pub fn get_host(&self) -> &str { - &self.host - } - /// Returns the remote's motd. - pub fn get_motd(&self) -> Result { - let url = format!("http://{}/motd", &self.host); - let response = reqwest::blocking::get(url).or(Err("HTTP request failed"))?; + pub async fn fetch_motd(&self) -> Result { + let url = format!("https://{}/motd", &self.host); + let response = reqwest::get(url).await?; let status = response.status(); - let content = response.text().or(Err("HTTP request failed"))?; - match status { - reqwest::StatusCode::OK => Ok(content), - - _ => Err(format!("Failed to retrieve motd: {}", status)), + StatusCode::OK => Ok(response.text().await?), + _ => bail!("Failed to retrieve motd (status {status})"), } } /// Fetches the list of all the packages from the remote. pub async fn fetch_list(&self) -> Result> { - let url = format!("http://{}/package", &self.host); + let url = format!("https://{}/package", &self.host); let response = reqwest::get(url).await?; let status = response.status(); - let content = response.text().await?; - match status { - reqwest::StatusCode::OK => Ok(serde_json::from_str(&content)?), - - _ => Err(anyhow!( - "Failed to retrieve packages list from remote: {}", - status - )), + StatusCode::OK => Ok(response.json().await?), + _ => bail!("Failed to retrieve packages list from remote (status {status})"), } } /// Returns the download size of the package `package` in bytes. pub async fn get_size(&self, package: &Package) -> Result { let url = format!( - "http://{}/package/{}/version/{}/archive", - self.host, - package.get_name(), - package.get_version() + "https://{}/package/{}/version/{}/archive", + self.host, package.name, package.version ); let client = reqwest::Client::new(); let response = client.head(url).send().await?; let len = response .content_length() .ok_or_else(|| anyhow!("Content-Length field not present in response"))?; - Ok(len) } @@ -124,13 +103,10 @@ impl Remote { package: &Package, ) -> Result { let url = format!( - "http://{}/package/{}/version/{}/archive", - self.host, - package.get_name(), - package.get_version() + "https://{}/package/{}/version/{}/archive", + self.host, package.name, package.version ); - - let path = repo.get_archive_path(package.get_name(), package.get_version()); + let path = repo.get_archive_path(&package.name, &package.version); DownloadTask::new(&url, &path).await.map_err(Into::into) } } diff --git a/common/src/util.rs b/common/src/util.rs index 97041c5..3eaadea 100644 --- a/common/src/util.rs +++ b/common/src/util.rs @@ -2,20 +2,15 @@ use bzip2::read::BzDecoder; use flate2::read::GzDecoder; -use rand::distributions::Alphanumeric; -use rand::{thread_rng, Rng}; -use serde::Deserialize; -use serde::Serialize; -use std::fs; -use std::fs::File; -use std::fs::OpenOptions; -use std::io; -use std::io::BufReader; -use std::io::BufWriter; -use std::io::Read; -use std::os::unix; -use std::path::Path; -use std::path::PathBuf; +use rand::{distributions::Alphanumeric, thread_rng, Rng}; +use std::{ + fs, + fs::{File, OpenOptions}, + io, + io::Read, + os::unix, + path::{Path, PathBuf}, +}; use tar::Archive; use xz2::read::XzDecoder; @@ -90,66 +85,25 @@ pub fn read_package_archive(path: &Path) -> io::Result>> } /// Copies the content of the directory `src` to the directory `dst` recursively. +/// +/// **Note**: the parent directory of `dst` must exist. pub fn recursive_copy(src: &Path, dst: &Path) -> io::Result<()> { + let src_metadata = fs::metadata(src)?; + fs::create_dir(dst)?; for entry in fs::read_dir(src)? { - let entry = entry?; - let file_type = entry.file_type()?; - let to = dst.join(entry.file_name()); - + let from = entry?; + let to = dst.join(from.file_name()); + let file_type = from.file_type()?; if file_type.is_dir() { - // TODO Set timestamps, permissions and owner - fs::create_dir_all(&to)?; - recursive_copy(&entry.path(), &to)?; + recursive_copy(&from.path(), &to)?; } else if file_type.is_symlink() { - let _metadata = fs::symlink_metadata(entry.path())?; - let target = fs::read_link(entry.path())?; - - // TODO Set timestamps and owner + let target = fs::read_link(from.path())?; unix::fs::symlink(target, &to)?; } else { - fs::copy(entry.path(), &to)?; + fs::copy(from.path(), &to)?; } } - Ok(()) -} - -// TODO delete (reuse the version in maestro-utils) -/// Prints the given size in bytes into a human-readable form. -pub fn print_size(mut size: u64) { - let mut level = 0; - while level < 6 && size > 1024 { - size /= 1024; - level += 1; - } - - let suffix = match level { - 0 => "bytes", - 1 => "KiB", - 2 => "MiB", - 3 => "GiB", - 4 => "TiB", - 5 => "PiB", - 6 => "EiB", - - _ => return, - }; - - print!("{size} {suffix}"); -} - -// TODO: rework to allow deserialize from structs with lifetimes (currently unefficient) -/// Reads a JSON file. -pub fn read_json Deserialize<'a>>(file: &Path) -> io::Result { - let file = File::open(file)?; - let reader = BufReader::new(file); - Ok(serde_json::from_reader(reader)?) -} - -/// Writes a JSON file. -pub fn write_json(file: &Path, data: &T) -> io::Result<()> { - let file = File::create(file)?; - let writer = BufWriter::new(file); - Ok(serde_json::to_writer_pretty(writer, &data)?) + fs::set_permissions(dst, src_metadata.permissions()) } /// Concatenates the given paths. diff --git a/common/src/version.rs b/common/src/version.rs index 8f5c320..9e04cdb 100644 --- a/common/src/version.rs +++ b/common/src/version.rs @@ -1,22 +1,12 @@ //! The version structure represents the version of a package. -use serde::de::Error; -use serde::Deserialize; -use serde::Deserializer; -use serde::Serialize; -use serde::Serializer; -use std::cmp::min; -use std::cmp::Ordering; -use std::fmt; -use std::fmt::Display; -use std::fmt::Formatter; -use std::num::ParseIntError; - -/// Structure representing a version. +use serde::{de::Error, Deserialize, Deserializer, Serialize, Serializer}; +use std::{cmp::Ordering, fmt, num::ParseIntError}; + +/// A package version. #[derive(Clone, Eq, Hash, PartialEq)] pub struct Version { - /// Vector containing the version numbers. - numbers: Vec, + components: Vec, } impl Serialize for Version { @@ -24,7 +14,7 @@ impl Serialize for Version { where S: Serializer, { - serializer.serialize_str(&self.to_string()) + serializer.collect_str(self) } } @@ -33,8 +23,8 @@ impl<'de> Deserialize<'de> for Version { where D: Deserializer<'de>, { - let s: String = Deserialize::deserialize(deserializer)?; - s.as_str().try_into().map_err(D::Error::custom) + let s: &str = Deserialize::deserialize(deserializer)?; + s.try_into().map_err(Error::custom) } } @@ -43,27 +33,24 @@ impl TryFrom<&str> for Version { fn try_from(value: &str) -> Result { value + .trim() .split('.') .map(|n| n.parse::()) .collect::, _>>() .map(|numbers| Self { - numbers, + components: numbers, }) } } impl Ord for Version { fn cmp(&self, other: &Self) -> Ordering { - for i in 0..min(self.numbers.len(), other.numbers.len()) { - let cmp = self.numbers[i].cmp(&other.numbers[i]); - - match cmp { - Ordering::Equal => {} - - _ => return cmp, + for (left, right) in self.components.iter().zip(other.components.iter()) { + let cmp = left.cmp(right); + if cmp != Ordering::Equal { + return cmp; } } - Ordering::Equal } } @@ -74,21 +61,19 @@ impl PartialOrd for Version { } } -impl Display for Version { - fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { - for i in 0..self.numbers.len() { - write!(f, "{}", self.numbers[i])?; - - if i + 1 < self.numbers.len() { +impl fmt::Display for Version { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + for i in 0..self.components.len() { + write!(f, "{}", self.components[i])?; + if i + 1 < self.components.len() { write!(f, ".")?; } } - Ok(()) } } -/// Enumeration of contraints on a package's dependencies. +/// Constraints on a package's dependencies. #[derive(Clone, Eq, Hash, PartialEq)] pub enum VersionConstraint { /// Any version match. @@ -110,7 +95,7 @@ impl Serialize for VersionConstraint { where S: Serializer, { - serializer.serialize_str(&self.to_string()) + serializer.collect_str(self) } } @@ -119,8 +104,8 @@ impl<'de> Deserialize<'de> for VersionConstraint { where D: Deserializer<'de>, { - let s: String = Deserialize::deserialize(deserializer)?; - s.as_str().try_into().map_err(D::Error::custom) + let s: &str = Deserialize::deserialize(deserializer)?; + s.try_into().map_err(Error::custom) } } @@ -128,14 +113,13 @@ impl TryFrom<&str> for VersionConstraint { type Error = ParseIntError; fn try_from(value: &str) -> Result { - match value { + match value.trim() { "*" => Ok(Self::Any), s if s.starts_with('=') => Ok(Self::Equal(Version::try_from(&s[1..])?)), s if s.starts_with("<=") => Ok(Self::LessOrEqual(Version::try_from(&s[2..])?)), s if s.starts_with('<') => Ok(Self::Less(Version::try_from(&s[1..])?)), s if s.starts_with(">=") => Ok(Self::GreaterOrEqual(Version::try_from(&s[2..])?)), s if s.starts_with('>') => Ok(Self::Greater(Version::try_from(&s[1..])?)), - _ => Ok(Self::Equal(Version::try_from(value)?)), } } @@ -157,15 +141,15 @@ impl VersionConstraint { } } -impl Display for VersionConstraint { - fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { +impl fmt::Display for VersionConstraint { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match self { Self::Any => write!(f, "*"), - Self::Equal(v) => write!(f, "={}", v), - Self::LessOrEqual(v) => write!(f, "<={}", v), - Self::Less(v) => write!(f, "<{}", v), - Self::GreaterOrEqual(v) => write!(f, ">={}", v), - Self::Greater(v) => write!(f, ">{}", v), + Self::Equal(v) => write!(f, "={v}"), + Self::LessOrEqual(v) => write!(f, "<={v}"), + Self::Less(v) => write!(f, "<{v}"), + Self::GreaterOrEqual(v) => write!(f, ">={v}"), + Self::Greater(v) => write!(f, ">{v}"), } } } diff --git a/rustfmt.toml b/rustfmt.toml index 073bd0d..1d340a3 100644 --- a/rustfmt.toml +++ b/rustfmt.toml @@ -1,10 +1,15 @@ blank_lines_upper_bound = 1 comment_width = 99 condense_wildcard_suffixes = true +format_code_in_doc_comments = true +group_imports = "One" hard_tabs = true hex_literal_case = "Lower" +imports_granularity = "Crate" +imports_indent = "Block" +max_width = 99 newline_style = "Unix" reorder_impl_items = true struct_lit_single_line = false use_field_init_shorthand = true -wrap_comments = true +wrap_comments = true \ No newline at end of file diff --git a/server/Cargo.toml b/server/Cargo.toml index 77619b1..16cda69 100644 --- a/server/Cargo.toml +++ b/server/Cargo.toml @@ -4,9 +4,9 @@ version = "0.1.0" edition = "2021" [dependencies] -actix-files = "0.6.6" -actix-web = "4.9.0" +axum = "0.7.7" common = { path = "../common" } -env_logger = "0.11.5" -serde = { version = "1.0.210", features = ["derive"] } -serde_json = "1.0.128" +envy = "0.4.2" +serde = { version = "1.0.214", features = ["derive"] } +tracing = "0.1.40" +tracing-subscriber = "0.3.18" diff --git a/server/src/config.rs b/server/src/config.rs deleted file mode 100644 index 96ee7b5..0000000 --- a/server/src/config.rs +++ /dev/null @@ -1,31 +0,0 @@ -//! This module handles the server's configuration file. - -use common::util; -use serde::Deserialize; -use serde::Serialize; -use std::io; -use std::path::Path; -use std::path::PathBuf; - -/// The path to the configuration file. -const CONFIG_FILE: &str = "config.json"; - -/// Structure representing the server's configuration. -#[derive(Deserialize, Serialize)] -pub struct Config { - /// The server's port. - pub port: u16, - - /// The server's motd. - pub motd: String, - - /// The path to the repository containing the server's packages. - pub repo_path: PathBuf, -} - -impl Config { - /// Reads the configuration from file. - pub fn read() -> io::Result { - util::read_json(Path::new(CONFIG_FILE)) - } -} diff --git a/server/src/global_data.rs b/server/src/global_data.rs deleted file mode 100644 index afa3b42..0000000 --- a/server/src/global_data.rs +++ /dev/null @@ -1,12 +0,0 @@ -//! This module implements the global data structure. - -use common::repository::Repository; - -/// Structure storing data used all across the server. -pub struct GlobalData { - /// The server's motd. - pub motd: String, - - /// The server's repository. - pub repo: Repository, -} diff --git a/server/src/main.rs b/server/src/main.rs index 0bc404c..c1e0bd7 100644 --- a/server/src/main.rs +++ b/server/src/main.rs @@ -1,57 +1,50 @@ //! The blimp server serves packages to be installed by the package manager. -mod config; -mod global_data; -mod package; -mod util; - -use actix_web::{get, middleware, web, App, HttpResponse, HttpServer, Responder}; -use common::repository::Repository; -use config::Config; -use global_data::GlobalData; -use std::env; -use std::io; - -#[get("/")] -async fn root() -> impl Responder { - let body = format!("Blimp server version {}", env!("CARGO_PKG_VERSION")); - HttpResponse::Ok().body(body) +mod route; + +use axum::{routing::get, Router}; +use common::{repository::Repository, tokio}; +use serde::Deserialize; +use std::{io, path::PathBuf, sync::Arc}; + +/// The server's configuration. +#[derive(Deserialize)] +pub struct Config { + /// The server's port. + pub port: u16, + /// The server's motd. + pub motd: String, + /// The path to the repository containing the server's packages. + pub repo_path: String, } -#[get("/motd")] -async fn motd(data: web::Data) -> impl Responder { - HttpResponse::Ok().body(data.motd.clone()) +/// The server's global context. +pub struct Context { + /// The server's motd. + motd: String, + /// The server's repository. + repo: Repository, } -#[actix_web::main] +#[tokio::main] async fn main() -> io::Result<()> { - // Reading config and initializing global data - let config = Config::read()?; - let port = config.port; - - let data = web::Data::new(GlobalData { + tracing_subscriber::fmt::init(); + let config: Config = envy::from_env().expect("configuration"); + let ctx = Arc::new(Context { motd: config.motd, - - repo: Repository::load(config.repo_path.clone())?, + repo: Repository::load(PathBuf::from(config.repo_path))?, }); - - // Enabling logging - env::set_var("RUST_LOG", "actix_web=info"); - env_logger::init(); - - HttpServer::new(move || { - App::new() - .wrap(middleware::Logger::new( - "[%t] %a: %r - Response: %s (in %D ms)", - )) - .app_data(data.clone()) - .service(root) - .service(motd) - .service(package::list) - .service(package::info) - .service(package::archive) - }) - .bind(format!("0.0.0.0:{}", port))? - .run() - .await + let router = Router::new() + .route("/", get(route::root)) + .route("/motd", get(route::motd)) + .route("/package", get(route::package::list)) + .route("/package/:name/version/:version", get(route::package::info)) + .route( + "/package/:name/version/:version/archive", + get(route::package::archive), + ) + // TODO logging layer + .with_state(ctx); + let listener = tokio::net::TcpListener::bind(format!("0.0.0.0:{}", config.port)).await?; + axum::serve(listener, router).await } diff --git a/server/src/package.rs b/server/src/package.rs deleted file mode 100644 index 9f2dd25..0000000 --- a/server/src/package.rs +++ /dev/null @@ -1,66 +0,0 @@ -use crate::global_data::GlobalData; -use crate::util; -use actix_files::NamedFile; -use actix_web::{error, get, web, HttpRequest, HttpResponse, Responder}; -use common::version::Version; - -#[get("/package")] -async fn list(data: web::Data) -> actix_web::Result { - data.repo - .list_packages() - .map(|packages| HttpResponse::Ok().json(packages)) - .map_err(|e| error::ErrorInternalServerError(e.to_string())) -} - -#[get("/package/{name}/version/{version}")] -async fn info( - path: web::Path<(String, String)>, - data: web::Data, -) -> actix_web::Result { - let (name, version) = path.into_inner(); - - if !util::is_correct_name(&name) { - return Err(error::ErrorBadRequest("invalid package name `{name}`")); - } - let version = - Version::try_from(version.as_str()).map_err(|e| error::ErrorNotFound(e.to_string()))?; - let package = data - .repo - .get_package(&name, &version) - .map_err(|e| error::ErrorInternalServerError(e.to_string()))?; - - match package { - Some(p) => Ok(HttpResponse::Ok().json(p)), - None => Ok(HttpResponse::NotFound().finish()), - } -} - -#[get("/package/{name}/version/{version}/archive")] -async fn archive( - req: HttpRequest, - path: web::Path<(String, String)>, - data: web::Data, -) -> actix_web::Result { - let (name, version) = path.into_inner(); - - if !util::is_correct_name(&name) { - return Err(error::ErrorBadRequest("invalid package name `{name}`")); - } - let version = - Version::try_from(version.as_str()).map_err(|e| error::ErrorNotFound(e.to_string()))?; - let package = data - .repo - .get_package(&name, &version) - .map_err(|e| error::ErrorInternalServerError(e.to_string()))?; - - if package.is_some() { - let archive_path = data.repo.get_archive_path(&name, &version); - - let req = NamedFile::open(archive_path) - .map_err(|e| error::ErrorInternalServerError(e.to_string()))? - .into_response(&req); - Ok(req) - } else { - Ok(HttpResponse::NotFound().finish()) - } -} diff --git a/server/src/route/mod.rs b/server/src/route/mod.rs new file mode 100644 index 0000000..8861ce2 --- /dev/null +++ b/server/src/route/mod.rs @@ -0,0 +1,15 @@ +//! Endpoints implementations. + +pub mod package; + +use crate::Context; +use axum::extract::State; +use std::sync::Arc; + +pub async fn root() -> &'static str { + concat!("Blimp server version ", env!("CARGO_PKG_VERSION")) +} + +pub async fn motd(State(ctx): State>) -> String { + ctx.motd.clone() +} diff --git a/server/src/route/package.rs b/server/src/route/package.rs new file mode 100644 index 0000000..5f3f552 --- /dev/null +++ b/server/src/route/package.rs @@ -0,0 +1,84 @@ +//! Package endpoints. + +use crate::Context; +use axum::{ + body::Body, + extract::{Path, State}, + http::{header::CONTENT_TYPE, StatusCode}, + response::{IntoResponse, Response}, + Json, +}; +use common::{package, tokio::fs::File, tokio_util::io::ReaderStream, version::Version}; +use std::sync::Arc; +use tracing::error; + +/// Endpoint to list packages. +pub async fn list(State(ctx): State>) -> Response { + let res = ctx.repo.list_packages(); + match res { + Ok(packages) => Json(packages).into_response(), + Err(error) => { + error!(%error, "could not list packages"); + (StatusCode::INTERNAL_SERVER_ERROR, "internal server error").into_response() + } + } +} + +/// Endpoint to get information about a package. +pub async fn info( + Path((name, version)): Path<(String, String)>, + State(ctx): State>, +) -> Response { + if !package::is_valid_name(&name) { + return (StatusCode::BAD_REQUEST, "invalid package name").into_response(); + } + let Ok(version) = Version::try_from(version.as_str()) else { + return (StatusCode::BAD_REQUEST, "invalid package version").into_response(); + }; + let res = ctx.repo.get_package(&name, &version); + match res { + Ok(Some(pkg)) => Json(pkg).into_response(), + Ok(None) => (StatusCode::NOT_FOUND, "package or version not found").into_response(), + Err(error) => { + error!(%error, name, %version, "could read package"); + (StatusCode::INTERNAL_SERVER_ERROR, "internal server error").into_response() + } + } +} + +/// Endpoint to get the package's archive. +pub async fn archive( + Path((name, version)): Path<(String, String)>, + State(ctx): State>, +) -> Response { + if !package::is_valid_name(&name) { + return (StatusCode::BAD_REQUEST, "invalid package name").into_response(); + } + let Ok(version) = Version::try_from(version.as_str()) else { + return (StatusCode::BAD_REQUEST, "invalid package version").into_response(); + }; + // Check package exists + let res = ctx.repo.get_package(&name, &version); + match res { + Ok(Some(_)) => {} + Ok(None) => { + return (StatusCode::NOT_FOUND, "package or version not found").into_response() + } + Err(error) => { + error!(%error, name, %version, "could read package"); + return (StatusCode::INTERNAL_SERVER_ERROR, "internal server error").into_response(); + } + } + // Read archive + let archive_path = ctx.repo.get_archive_path(&name, &version); + let res = File::open(&archive_path).await; + let file = match res { + Ok(f) => f, + Err(error) => { + error!(%error, name, %version, path = %archive_path.display(), "could not read package archive"); + return (StatusCode::INTERNAL_SERVER_ERROR, "internal server error").into_response(); + } + }; + let body = Body::from_stream(ReaderStream::new(file)); + ([(CONTENT_TYPE, "application/x-gzip-compressed")], body).into_response() +} diff --git a/server/src/util.rs b/server/src/util.rs deleted file mode 100644 index 963ded7..0000000 --- a/server/src/util.rs +++ /dev/null @@ -1,7 +0,0 @@ -//! This module implements utility functions. - -/// Tells whether the given package name is correct. -pub fn is_correct_name(name: &str) -> bool { - name.chars() - .all(|c| c.is_ascii_alphanumeric() || c == '-' || c == '_') -}