diff --git a/.cargo/config b/.cargo/config.toml similarity index 99% rename from .cargo/config rename to .cargo/config.toml index 835e3617..1c058773 100644 --- a/.cargo/config +++ b/.cargo/config.toml @@ -2,3 +2,4 @@ # If we're targetting Windows, configure a custom linker so that `cargo` # won't attempt to use the system GCC. linker = "x86_64-w64-mingw32-gcc" + diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 00000000..9784ad97 --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,85 @@ +name: CI + +on: + push: + branches: + - main + - modernize + pull_request: + +permissions: + contents: read + +jobs: + test: + name: Test + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - name: Install Rust + uses: dtolnay/rust-toolchain@stable + + - name: Cache dependencies + uses: Swatinem/rust-cache@v2 + + - name: Run tests + run: cargo test --all-features + + check: + name: Check + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - name: Install Rust + uses: dtolnay/rust-toolchain@stable + + - name: Cache dependencies + uses: Swatinem/rust-cache@v2 + + - name: Run cargo check + run: cargo check --all-features + + fmt: + name: Format + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - name: Install Rust + uses: dtolnay/rust-toolchain@stable + with: + components: rustfmt + + - name: Check formatting + run: cargo fmt --all -- --check + + clippy: + name: Clippy + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - name: Install Rust + uses: dtolnay/rust-toolchain@stable + with: + components: clippy + + - name: Cache dependencies + uses: Swatinem/rust-cache@v2 + + - name: Run clippy + run: cargo clippy --all-features -- -D warnings + + deny: + name: Deny + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - name: Install cargo-deny + run: cargo install --locked cargo-deny + + - name: Run cargo deny + run: cargo deny check advisories licenses sources diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 00000000..e892842d --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,140 @@ +name: Release + +on: + push: + tags: + - 'v*' + +permissions: + contents: write + +jobs: + validate: + name: Validate version + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - name: Extract version from tag + id: tag_version + run: | + TAG="${GITHUB_REF#refs/tags/v}" + echo "version=$TAG" >> $GITHUB_OUTPUT + echo "Tag version: $TAG" + + - name: Extract version from Cargo.toml + id: cargo_version + run: | + CARGO_VERSION=$(grep '^version = ' Cargo.toml | head -1 | cut -d'"' -f2) + echo "version=$CARGO_VERSION" >> $GITHUB_OUTPUT + echo "Cargo.toml version: $CARGO_VERSION" + + - name: Validate versions match + run: | + if [ "${{ steps.tag_version.outputs.version }}" != "${{ steps.cargo_version.outputs.version }}" ]; then + echo "Error: Tag version (${{ steps.tag_version.outputs.version }}) does not match Cargo.toml version (${{ steps.cargo_version.outputs.version }})" + exit 1 + fi + echo "Version validation passed: ${{ steps.tag_version.outputs.version }}" + + build: + name: Build ${{ matrix.target }} + needs: validate + runs-on: ${{ matrix.os }} + strategy: + matrix: + include: + - os: ubuntu-latest + target: x86_64-unknown-linux-musl + archive_name: cage-${{ github.ref_name }}-linux-x86_64.zip + - os: macos-latest + target: x86_64-apple-darwin + archive_name: cage-${{ github.ref_name }}-macos-x86_64.zip + - os: macos-latest + target: aarch64-apple-darwin + archive_name: cage-${{ github.ref_name }}-macos-aarch64.zip + - os: windows-latest + target: x86_64-pc-windows-msvc + archive_name: cage-${{ github.ref_name }}-windows-x86_64.zip + + steps: + - uses: actions/checkout@v4 + + - name: Install Rust + uses: dtolnay/rust-toolchain@stable + with: + targets: ${{ matrix.target }} + + - name: Install musl tools (Linux) + if: matrix.target == 'x86_64-unknown-linux-musl' + run: | + sudo apt-get update + sudo apt-get install -y musl-tools + + - name: Build + run: cargo build --release --target ${{ matrix.target }} + + - name: Create archive (Unix) + if: runner.os != 'Windows' + run: | + cd target/${{ matrix.target }}/release + zip ../../../${{ matrix.archive_name }} cage + + - name: Create archive (Windows) + if: runner.os == 'Windows' + shell: pwsh + run: | + cd target/${{ matrix.target }}/release + Compress-Archive -Path cage.exe -DestinationPath ../../../${{ matrix.archive_name }} + + - name: Upload artifact + uses: actions/upload-artifact@v4 + with: + name: ${{ matrix.target }} + path: ${{ matrix.archive_name }} + + release: + name: Create GitHub Release + needs: build + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - name: Download all artifacts + uses: actions/download-artifact@v4 + with: + path: artifacts + + - name: Prepare release files + run: | + mkdir release-files + find artifacts -name "*.zip" -exec cp {} release-files/ \; + ls -lh release-files/ + + - name: Extract changelog for this version + id: changelog + run: | + VERSION="${GITHUB_REF#refs/tags/v}" + echo "Extracting changelog for version $VERSION" + + # Extract the section between this version and the next one + CHANGELOG=$(awk "/## $VERSION/,/## [0-9]/" CHANGELOG.md | sed '1d;$d') + + # If empty, use a default message + if [ -z "$CHANGELOG" ]; then + CHANGELOG="Release $VERSION" + fi + + # Save to file for multi-line handling + echo "$CHANGELOG" > changelog.txt + + - name: Create Release + uses: softprops/action-gh-release@v2 + with: + files: release-files/* + body_path: changelog.txt + draft: false + prerelease: false + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + diff --git a/CHANGELOG.md b/CHANGELOG.md index 6d18e4ce..af7dbf8b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,15 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## Unreleased + +## 0.4.0 - 2025-10-29 + +### Changed + +- Replaced `boondock` Docker client with `bollard` for better async/await support and active maintenance. +- Updated `tokio` runtime from 0.2 to 1.x for better async compatibility. + ## 0.3.6 - 2021-05-10 ### Fixed diff --git a/Cargo.lock b/Cargo.lock index 1b10a5c5..a14fc24e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1,215 +1,234 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. +version = 4 + [[package]] -name = "addr2line" -version = "0.15.1" +name = "addr" +version = "0.15.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "03345e98af8f3d786b6d9f656ccfa6ac316d954e92bc4841f0bba20789d5fb5a" +checksum = "a93b8a41dbe230ad5087cc721f8d41611de654542180586b315d9f4cf6b72bef" dependencies = [ - "gimli", + "psl", + "psl-types", ] -[[package]] -name = "adler" -version = "1.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" - [[package]] name = "aho-corasick" -version = "0.7.18" +version = "1.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e37cfd5e7657ada45f742d6e99ca5788580b5c529dc78faf11ece6dc702656f" +checksum = "ddd31a130427c27518df266943a5308ed92d4b226cc639f5a8f1002816174301" dependencies = [ "memchr", ] [[package]] -name = "ansi_term" -version = "0.11.0" +name = "android_system_properties" +version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ee49baf6cb617b853aa8d93bf420db2383fab46d314482ca2803b40d5fde979b" +checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311" dependencies = [ - "winapi 0.3.9", + "libc", ] [[package]] -name = "anyhow" -version = "1.0.40" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "28b2cd92db5cbd74e8e5028f7e27dd7aa3090e89e4f2a197cc7c8dfb69c7063b" - -[[package]] -name = "atty" -version = "0.2.14" +name = "anstream" +version = "0.6.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8" +checksum = "43d5b281e737544384e969a5ccad3f1cdd24b48086a0fc1b2a5262a26b8f4f4a" dependencies = [ - "hermit-abi", - "libc", - "winapi 0.3.9", + "anstyle", + "anstyle-parse", + "anstyle-query", + "anstyle-wincon", + "colorchoice", + "is_terminal_polyfill", + "utf8parse", ] [[package]] -name = "autocfg" -version = "0.1.7" +name = "anstyle" +version = "1.0.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d49d90015b3c36167a20fe2810c5cd875ad504b39cff3d4eae7977e6b7c1cb2" +checksum = "5192cca8006f1fd4f7237516f40fa183bb07f8fbdfedaa0036de5ea9b0b45e78" [[package]] -name = "autocfg" -version = "1.0.1" +name = "anstyle-parse" +version = "0.2.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a" +checksum = "4e7644824f0aa2c7b9384579234ef10eb7efb6a0deb83f9630a49594dd9c15c2" +dependencies = [ + "utf8parse", +] [[package]] -name = "backtrace" -version = "0.3.59" +name = "anstyle-query" +version = "1.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4717cfcbfaa661a0fd48f8453951837ae7e8f81e481fbb136e3202d72805a744" +checksum = "9e231f6134f61b71076a3eab506c379d4f36122f2af15a9ff04415ea4c3339e2" dependencies = [ - "addr2line", - "cc", - "cfg-if 1.0.0", - "libc", - "miniz_oxide", - "object", - "rustc-demangle", + "windows-sys 0.60.2", ] [[package]] -name = "base64" -version = "0.10.1" +name = "anstyle-wincon" +version = "3.0.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b25d992356d2eb0ed82172f5248873db5560c4721f564b13cb5193bda5e668e" +checksum = "3e0633414522a32ffaac8ac6cc8f748e090c5717661fddeea04219e2344f5f2a" dependencies = [ - "byteorder", + "anstyle", + "once_cell_polyfill", + "windows-sys 0.60.2", ] [[package]] -name = "base64" -version = "0.11.0" +name = "anyhow" +version = "1.0.100" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a23eb6b1614318a8071c9b2521f36b424b2c83db5eb3a0fead4a6c0809af6e61" + +[[package]] +name = "arraydeque" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7d902e3d592a523def97af8f317b08ce16b7ab854c1985a0c671e6f15cebc236" + +[[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.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b41b7ea54a0c9d92199de89e20e58d49f02f8e699814ef3fdf266f6f748d15c7" +checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8" [[package]] name = "base64" -version = "0.12.3" +version = "0.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3441f0f7b02788e948e47f457ca01f1d7e6d92c693bc132c22b087d3141c03ff" +checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8" [[package]] name = "base64" -version = "0.13.0" +version = "0.21.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "904dfeac50f3cdaba28fc6f57fdcddb75f49ed61346676a78c4ffe55877802fd" +checksum = "9d297deb1925b89f2ccc13d7635fa0714f12c87adce1c75356b39ca9b7178567" [[package]] -name = "bitflags" -version = "1.2.1" +name = "base64" +version = "0.22.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693" +checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" [[package]] -name = "block-buffer" -version = "0.7.3" +name = "bit-set" +version = "0.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0940dc441f31689269e10ac70eb1002a3a1d3ad1390e030043662eb7fe4688b" +checksum = "0700ddab506f33b20a03b13996eccd309a48e5ff77d0d95926aa0210fb4e95f1" dependencies = [ - "block-padding", - "byte-tools", - "byteorder", - "generic-array", + "bit-vec", ] [[package]] -name = "block-padding" -version = "0.1.5" +name = "bit-vec" +version = "0.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa79dedbb091f449f1f39e53edf88d5dbe95f895dae6135a8d7b881fb5af73f5" -dependencies = [ - "byte-tools", -] +checksum = "349f9b6a179ed607305526ca489b34ad0a41aed5f7980fa90eb03160b69598fb" [[package]] -name = "boondock" -version = "0.1.0-alpha.1" +name = "bitflags" +version = "1.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7be9318bc47be9a92441f5124ca83eca3943f47676a62e3bcf4be96970073ddd" -dependencies = [ - "ct-logs", - "dirs 2.0.2", - "error-chain", - "futures 0.3.14", - "hyper 0.13.10", - "hyper-rustls", - "hyperlocal", - "log", - "rustls", - "rustls-native-certs", - "serde", - "serde_derive", - "serde_json", - "tokio 0.2.25", - "url 2.2.2", - "webpki-roots", -] +checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] -name = "bumpalo" -version = "3.6.1" +name = "bitflags" +version = "2.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "63396b8a4b9de3f4fdfb320ab6080762242f66a8ef174c49d8e19b674db4cdbe" +checksum = "812e12b5285cc515a9c72a5c1d3b6d46a19dac5acfef5265968c166106e31dd3" [[package]] -name = "byte-tools" -version = "0.3.1" +name = "block-buffer" +version = "0.10.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3b5ca7a04898ad4bcd41c90c5285445ff5b791899bb1b0abdd2a2aa791211d7" +checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71" +dependencies = [ + "generic-array", +] [[package]] -name = "byteorder" -version = "1.4.3" +name = "bollard" +version = "0.19.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610" +checksum = "ec7646ee90964aa59e9f832a67182791396a19a5b1d76eb17599a8310a7e2e09" +dependencies = [ + "base64 0.22.1", + "bollard-stubs", + "bytes", + "futures-core", + "futures-util", + "hex", + "http 1.3.1", + "http-body-util", + "hyper 1.7.0", + "hyper-named-pipe", + "hyper-util", + "hyperlocal", + "log", + "pin-project-lite", + "serde", + "serde_derive", + "serde_json", + "serde_repr", + "serde_urlencoded", + "thiserror", + "tokio", + "tokio-util", + "tower-service", + "url", + "winapi", +] [[package]] -name = "bytes" -version = "0.4.12" +name = "bollard-stubs" +version = "1.49.1-rc.28.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "206fdffcfa2df7cbe15601ef46c813fce0965eb3286db6b56c583b814b51c81c" +checksum = "5731fe885755e92beff1950774068e0cae67ea6ec7587381536fca84f1779623" dependencies = [ - "byteorder", - "either", - "iovec", + "serde", + "serde_json", + "serde_repr", + "serde_with", ] [[package]] -name = "bytes" -version = "0.5.6" +name = "bumpalo" +version = "3.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0e4cec68f03f32e44924783795810fa50a7035d8c8ebe78580ad7e6c703fba38" +checksum = "46c5e41b57b8bba42a04676d81cb89e9ee8e859a1a66f80a5a72e1cb76b34d43" [[package]] name = "bytes" -version = "1.0.1" +version = "1.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b700ce4376041dcd0a327fd0097c41095743c4c8af8887265942faf1100bd040" +checksum = "d71b6127be86fdcfddb610f7182ac57211d4b18a3e9c82eb2d17662f2227ad6a" [[package]] name = "cage" -version = "0.3.6" +version = "0.4.0" dependencies = [ - "boondock", + "anyhow", + "bollard", "clap", + "clap_complete", "cli_test_dir", "colored", - "compose_yml", "copy_dir", - "dirs 3.0.2", + "dirs", "env_logger", - "error-chain", - "failure", + "faraday_compose_yml", "glob", "handlebars", "hashicorp_vault", @@ -218,540 +237,486 @@ dependencies = [ "lazy_static", "log", "openssl-probe", - "rand 0.7.3", + "rand 0.9.2", "rayon", "regex", "retry", - "semver 0.10.0", + "semver", "serde", "serde_derive", "serde_json", "serde_yaml", "shlex", - "tokio 0.2.25", - "url 2.2.2", - "yaml-rust 0.3.5", + "thiserror", + "tokio", + "url", ] [[package]] name = "cc" -version = "1.0.67" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3c69b077ad434294d3ce9f1f6143a2a4b89a8a2d54ef813d85003a4fd1137fd" - -[[package]] -name = "cfg-if" -version = "0.1.10" +version = "1.2.43" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822" +checksum = "739eb0f94557554b3ca9a86d2d37bebd49c5e6d0c1d2bda35ba5bdac830befc2" +dependencies = [ + "find-msvc-tools", + "shlex", +] [[package]] name = "cfg-if" -version = "1.0.0" +version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" +checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801" [[package]] name = "chrono" -version = "0.4.19" +version = "0.4.42" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "670ad68c9088c2a963aaa298cb369688cf3f9465ce5e2d4ca10e6e0098a1ce73" +checksum = "145052bdd345b87320e369255277e3fb5152762ad123a901ef5c262dd38fe8d2" dependencies = [ - "libc", - "num-integer", + "iana-time-zone", + "js-sys", "num-traits", - "time", - "winapi 0.3.9", + "serde", + "wasm-bindgen", + "windows-link", ] [[package]] name = "clap" -version = "2.33.3" +version = "4.5.51" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "37e58ac78573c40708d45522f0d80fa2f01cc4f9b4e2bf749807255454312002" +checksum = "4c26d721170e0295f191a69bd9a1f93efcdb0aff38684b61ab5750468972e5f5" dependencies = [ - "ansi_term", - "atty", - "bitflags", - "strsim", - "textwrap", - "unicode-width", - "vec_map", - "yaml-rust 0.3.5", + "clap_builder", + "clap_derive", ] [[package]] -name = "cli_test_dir" -version = "0.1.7" +name = "clap_builder" +version = "4.5.51" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2bc63338a59538d4f4b767dfb6082e4d26736aadb5100894b76039a04d6ad519" +checksum = "75835f0c7bf681bfd05abe44e965760fea999a5286c6eb2d59883634fd02011a" +dependencies = [ + "anstream", + "anstyle", + "clap_lex", + "strsim", +] [[package]] -name = "cloudabi" -version = "0.0.3" +name = "clap_complete" +version = "4.5.59" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ddfc5b9aa5d4507acaf872de71051dfd0e309860e88966e1051e462a077aac4f" +checksum = "2348487adcd4631696ced64ccdb40d38ac4d31cae7f2eec8817fcea1b9d1c43c" dependencies = [ - "bitflags", + "clap", ] [[package]] -name = "colored" -version = "2.0.0" +name = "clap_derive" +version = "4.5.49" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b3616f750b84d8f0de8a58bda93e08e2a81ad3f523089b05f1dffecab48c6cbd" +checksum = "2a0b5487afeab2deb2ff4e03a807ad1a03ac532ff5a2cee5d86884440c7f7671" dependencies = [ - "atty", - "lazy_static", - "winapi 0.3.9", + "heck", + "proc-macro2", + "quote", + "syn", ] [[package]] -name = "compose_yml" -version = "0.0.59" +name = "clap_lex" +version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a7ceddebf473645c64af12f1f9839a2127cf544371fc6ffc9838214706e9a226" -dependencies = [ - "lazy_static", - "log", - "regex", - "serde", - "serde_json", - "serde_yaml", - "thiserror", - "url 2.2.2", - "valico", - "void", - "yaml-rust 0.4.5", -] +checksum = "a1d728cc89cf3aee9ff92b05e62b19ee65a02b5702cff7d5a377e32c6ae29d8d" [[package]] -name = "cookie" -version = "0.12.0" +name = "cli_test_dir" +version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "888604f00b3db336d2af898ec3c1d5d0ddf5e6d462220f2ededc33a87ac4bbd5" -dependencies = [ - "time", - "url 1.7.2", -] +checksum = "cc7e8a289c9ba144ed96a2f5776b320192ccb2f22212b9aabf61fd15dedb4b3a" [[package]] -name = "cookie_store" -version = "0.7.0" +name = "colorchoice" +version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "46750b3f362965f197996c4448e4a0935e791bf7d6631bfce9ee0af3d24c919c" -dependencies = [ - "cookie", - "failure", - "idna 0.1.5", - "log", - "publicsuffix", - "serde", - "serde_json", - "time", - "try_from", - "url 1.7.2", -] +checksum = "b05b61dc5112cbb17e4b6cd61790d9845d13888356391624cbe7e41efeac1e75" [[package]] -name = "copy_dir" -version = "0.1.2" +name = "colored" +version = "3.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e4281031634644843bd2f5aa9c48cf98fc48d6b083bd90bb11becf10deaf8b0" +checksum = "fde0e0ec90c9dfb3b4b1a0891a7dcd0e2bffde2f7efed5fe7c9bb00e5bfb915e" dependencies = [ - "walkdir", + "windows-sys 0.59.0", ] [[package]] -name = "core-foundation" -version = "0.7.0" +name = "copy_dir" +version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "57d24c7a13c43e870e37c1556b74555437870a04514f7685f5b354e090567171" +checksum = "543d1dd138ef086e2ff05e3a48cf9da045da2033d16f8538fd76b86cd49b2ca3" dependencies = [ - "core-foundation-sys 0.7.0", - "libc", + "walkdir", ] [[package]] name = "core-foundation" -version = "0.9.1" +version = "0.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0a89e2ae426ea83155dccf10c0fa6b1463ef6d5fcb44cee0b224a408fa640a62" +checksum = "91e195e091a93c46f7102ec7818a2aa394e1e1771c3ab4825963fa03e45afb8f" dependencies = [ - "core-foundation-sys 0.8.2", + "core-foundation-sys", "libc", ] [[package]] name = "core-foundation-sys" -version = "0.7.0" +version = "0.8.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b3a71ab494c0b5b860bdc8407ae08978052417070c2ced38573a9157ad75b8ac" +checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" [[package]] -name = "core-foundation-sys" -version = "0.8.2" +name = "cpufeatures" +version = "0.2.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ea221b5284a47e40033bf9b66f35f984ec0ea2931eb03505246cd27a963f981b" +checksum = "59ed5838eebb26a2bb2e58f6d5b5316989ae9d08bab10e0e6d103e656d1b0280" +dependencies = [ + "libc", +] [[package]] -name = "crc32fast" -version = "1.2.1" +name = "crossbeam-deque" +version = "0.8.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "81156fece84ab6a9f2afdb109ce3ae577e42b1228441eded99bd77f627953b1a" +checksum = "9dd111b7b7f7d55b72c0a6ae361660ee5853c9af73f70c3c2ef6858b950e2e51" dependencies = [ - "cfg-if 1.0.0", + "crossbeam-epoch", + "crossbeam-utils", ] [[package]] -name = "crossbeam-channel" -version = "0.5.1" +name = "crossbeam-epoch" +version = "0.9.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "06ed27e177f16d65f0f0c22a213e17c696ace5dd64b14258b52f9417ccb52db4" +checksum = "5b82ac4a3c2ca9c3460964f020e1402edd5753411d7737aa39c3714ad1b5420e" dependencies = [ - "cfg-if 1.0.0", - "crossbeam-utils 0.8.4", + "crossbeam-utils", ] [[package]] -name = "crossbeam-deque" -version = "0.7.3" +name = "crossbeam-utils" +version = "0.8.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9f02af974daeee82218205558e51ec8768b48cf524bd01d550abe5573a608285" -dependencies = [ - "crossbeam-epoch 0.8.2", - "crossbeam-utils 0.7.2", - "maybe-uninit", -] +checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28" [[package]] -name = "crossbeam-deque" -version = "0.8.0" +name = "crypto-common" +version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "94af6efb46fef72616855b036a624cf27ba656ffc9be1b9a3c931cfc7749a9a9" +checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" dependencies = [ - "cfg-if 1.0.0", - "crossbeam-epoch 0.9.4", - "crossbeam-utils 0.8.4", + "generic-array", + "typenum", ] [[package]] -name = "crossbeam-epoch" -version = "0.8.2" +name = "darling" +version = "0.20.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "058ed274caafc1f60c4997b5fc07bf7dc7cca454af7c6e81edffe5f33f70dace" +checksum = "fc7f46116c46ff9ab3eb1597a45688b6715c6e628b5c133e288e709a29bcb4ee" dependencies = [ - "autocfg 1.0.1", - "cfg-if 0.1.10", - "crossbeam-utils 0.7.2", - "lazy_static", - "maybe-uninit", - "memoffset 0.5.6", - "scopeguard", + "darling_core", + "darling_macro", ] [[package]] -name = "crossbeam-epoch" -version = "0.9.4" +name = "darling_core" +version = "0.20.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "52fb27eab85b17fbb9f6fd667089e07d6a2eb8743d02639ee7f6a7a7729c9c94" +checksum = "0d00b9596d185e565c2207a0b01f8bd1a135483d02d9b7b0a54b11da8d53412e" dependencies = [ - "cfg-if 1.0.0", - "crossbeam-utils 0.8.4", - "lazy_static", - "memoffset 0.6.3", - "scopeguard", + "fnv", + "ident_case", + "proc-macro2", + "quote", + "strsim", + "syn", ] [[package]] -name = "crossbeam-queue" -version = "0.2.3" +name = "darling_macro" +version = "0.20.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "774ba60a54c213d409d5353bda12d49cd68d14e45036a285234c8d6f91f92570" +checksum = "fc34b93ccb385b40dc71c6fceac4b2ad23662c7eeb248cf10d529b7e055b6ead" dependencies = [ - "cfg-if 0.1.10", - "crossbeam-utils 0.7.2", - "maybe-uninit", + "darling_core", + "quote", + "syn", ] [[package]] -name = "crossbeam-utils" -version = "0.7.2" +name = "deranged" +version = "0.5.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3c7c73a2d1e9fc0886a08b93e98eb643461230d5f1925e4036204d5f2e261a8" +checksum = "ececcb659e7ba858fb4f10388c250a7252eb0a27373f1a72b8748afdd248e587" dependencies = [ - "autocfg 1.0.1", - "cfg-if 0.1.10", - "lazy_static", + "powerfmt", + "serde_core", ] [[package]] -name = "crossbeam-utils" -version = "0.8.4" +name = "derive_builder" +version = "0.20.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4feb231f0d4d6af81aed15928e58ecf5816aa62a2393e2c82f46973e92a9a278" +checksum = "507dfb09ea8b7fa618fcf76e953f4f5e192547945816d5358edffe39f6f94947" dependencies = [ - "autocfg 1.0.1", - "cfg-if 1.0.0", - "lazy_static", + "derive_builder_macro", ] [[package]] -name = "ct-logs" -version = "0.6.0" +name = "derive_builder_core" +version = "0.20.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4d3686f5fa27dbc1d76c751300376e167c5a43387f44bb451fd1c24776e49113" +checksum = "2d5bcf7b024d6835cfb3d473887cd966994907effbe9227e8c8219824d06c4e8" dependencies = [ - "sct", + "darling", + "proc-macro2", + "quote", + "syn", ] [[package]] -name = "digest" -version = "0.8.1" +name = "derive_builder_macro" +version = "0.20.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f3d0c8c8752312f9713efd397ff63acb9f85585afbf179282e720e7704954dd5" +checksum = "ab63b0e2bf4d5928aff72e83a7dace85d7bba5fe12dcc3c5a572d78caffd3f3c" dependencies = [ - "generic-array", + "derive_builder_core", + "syn", ] [[package]] -name = "dirs" -version = "2.0.2" +name = "digest" +version = "0.10.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "13aea89a5c93364a98e9b37b2fa237effbb694d5cfe01c5b70941f7eb087d5e3" +checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" dependencies = [ - "cfg-if 0.1.10", - "dirs-sys", + "block-buffer", + "crypto-common", ] [[package]] name = "dirs" -version = "3.0.2" +version = "6.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "30baa043103c9d0c2a57cf537cc2f35623889dc0d405e6c3cccfadbc81c71309" +checksum = "c3e8aa94d75141228480295a7d0e7feb620b1a5ad9f12bc40be62411e38cce4e" dependencies = [ "dirs-sys", ] [[package]] name = "dirs-sys" -version = "0.3.6" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "03d86534ed367a67548dc68113a0f5db55432fdfbb6e6f9d77704397d95d5780" +checksum = "e01a3366d27ee9890022452ee61b2b63a67e6f13f58900b651ff5665f0bb1fab" dependencies = [ "libc", + "option-ext", "redox_users", - "winapi 0.3.9", + "windows-sys 0.61.2", +] + +[[package]] +name = "displaydoc" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0" +dependencies = [ + "proc-macro2", + "quote", + "syn", ] [[package]] -name = "dtoa" -version = "0.4.8" +name = "downcast-rs" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75b325c5dbd37f80359721ad39aca5a29fb04c89279657cffdda8736d0c0b9d2" + +[[package]] +name = "dyn-clone" +version = "1.0.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "56899898ce76aaf4a0f24d914c97ea6ed976d42fec6ad33fcbb0a1103e07b2b0" +checksum = "d0881ea181b1df73ff77ffaaf9c7544ecc11e82fba9b5f27b262a3c73a332555" [[package]] name = "either" -version = "1.6.1" +version = "1.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e78d4f1cc4ae33bbfc157ed5d5a5ef3bc29227303d595861deb238fcec4e9457" +checksum = "48c757948c5ede0e46177b7add2e67155f70e33c07fea8284df6576da70b3719" [[package]] name = "encoding_rs" -version = "0.8.28" +version = "0.8.35" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "80df024fbc5ac80f87dfef0d9f5209a252f2a497f7f42944cff24d8253cac065" +checksum = "75030f3c4f45dafd7586dd6780965a8c7e8e285a5ecb86713e63a79c5b2766f3" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", ] [[package]] -name = "env_logger" -version = "0.7.1" +name = "env_filter" +version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "44533bbbb3bb3c1fa17d9f2e4e38bbbaf8396ba82193c4cb1b6445d711445d36" +checksum = "1bf3c259d255ca70051b30e2e95b5446cdb8949ac4cd22c0d7fd634d89f568e2" dependencies = [ - "atty", - "humantime", "log", "regex", - "termcolor", ] [[package]] -name = "error-chain" -version = "0.12.4" +name = "env_logger" +version = "0.11.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2d2f06b9cac1506ece98fe3231e3cc9c4410ec3d5b1f24ae1c8946f0742cdefc" +checksum = "13c863f0904021b108aa8b2f55046443e6b1ebde8fd4a15c399893aae4fa069f" dependencies = [ - "backtrace", - "version_check", + "anstream", + "anstyle", + "env_filter", + "jiff", + "log", ] [[package]] -name = "failure" -version = "0.1.8" +name = "equivalent" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d32e9bd16cc02eae7db7ef620b392808b89f6a5e16bb3497d159c6b92a0f4f86" -dependencies = [ - "backtrace", - "failure_derive", -] +checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f" [[package]] -name = "failure_derive" -version = "0.1.8" +name = "erased-serde" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aa4da3c766cd7a0db8242e326e9e4e081edd567072893ed320008189715366a4" +checksum = "6c138974f9d5e7fe373eb04df7cae98833802ae4b11c24ac7039a21d5af4b26c" dependencies = [ - "proc-macro2", - "quote", - "syn", - "synstructure", + "serde", ] [[package]] -name = "fake-simd" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e88a8acf291dafb59c2d96e8f59828f3838bb1a70398823ade51a84de6a6deed" - -[[package]] -name = "flate2" -version = "1.0.20" +name = "errno" +version = "0.3.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cd3aec53de10fe96d7d8c565eb17f2c687bb5518a2ec453b5b1252964526abe0" +checksum = "39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb" dependencies = [ - "cfg-if 1.0.0", - "crc32fast", "libc", - "miniz_oxide", + "windows-sys 0.61.2", ] [[package]] -name = "fnv" -version = "1.0.7" +name = "fancy-regex" +version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" +checksum = "b95f7c0680e4142284cf8b22c14a476e87d61b004a3a0861872b32ef7ead40a2" +dependencies = [ + "bit-set", + "regex", +] [[package]] -name = "foreign-types" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1" +name = "faraday_compose_yml" +version = "0.0.62" +source = "git+https://github.com/faradayio/compose_yml#d199bd5f5ae284542c63eb31b141afdf277f9b55" dependencies = [ - "foreign-types-shared", + "lazy_static", + "log", + "regex", + "serde", + "serde_json", + "serde_yaml", + "thiserror", + "url", + "valico", + "void", + "yaml-rust2", ] [[package]] -name = "foreign-types-shared" -version = "0.1.1" +name = "fastrand" +version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" +checksum = "37909eebbb50d72f9059c3b6d82c0463f2ff062c9e95845c43a6c9c0355411be" [[package]] -name = "form_urlencoded" -version = "1.0.1" +name = "find-msvc-tools" +version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5fc25a87fa4fd2094bffb06925852034d90a17f0d1e05197d4956d3555752191" -dependencies = [ - "matches", - "percent-encoding 2.1.0", -] +checksum = "52051878f80a721bb68ebfbc930e07b65ba72f2da88968ea5c06fd6ca3d3a127" [[package]] -name = "fuchsia-cprng" -version = "0.1.1" +name = "fnv" +version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a06f77d526c1a601b7c4cdd98f54b5eaabffc14d5f2f0296febdc7f357c6d3ba" +checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" [[package]] -name = "fuchsia-zircon" -version = "0.3.3" +name = "foldhash" +version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2e9763c69ebaae630ba35f74888db465e49e259ba1bc0eda7d06f4a067615d82" -dependencies = [ - "bitflags", - "fuchsia-zircon-sys", -] +checksum = "d9c4f5dac5e15c24eb999c26181a6ca40b39fe946cbe4c263c7209467bc83af2" [[package]] -name = "fuchsia-zircon-sys" -version = "0.3.3" +name = "foreign-types" +version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3dcaa9ae7725d12cdb85b3ad99a434db70b468c09ded17e012d86b5c1010f7a7" +checksum = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1" +dependencies = [ + "foreign-types-shared", +] [[package]] -name = "futures" -version = "0.1.31" +name = "foreign-types-shared" +version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3a471a38ef8ed83cd6e40aa59c1ffe17db6855c18e3604d9c4ed8c08ebc28678" +checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" [[package]] -name = "futures" -version = "0.3.14" +name = "form_urlencoded" +version = "1.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a9d5813545e459ad3ca1bff9915e9ad7f1a47dc6a91b627ce321d5863b7dd253" +checksum = "cb4cb245038516f5f85277875cdaa4f7d2c9a0fa0468de06ed190163b1581fcf" dependencies = [ - "futures-channel", - "futures-core", - "futures-executor", - "futures-io", - "futures-sink", - "futures-task", - "futures-util", + "percent-encoding", ] [[package]] name = "futures-channel" -version = "0.3.14" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce79c6a52a299137a6013061e0cf0e688fce5d7f1bc60125f520912fdb29ec25" +checksum = "2dff15bf788c671c1934e366d07e30c1814a8ef514e1af724a602e8a2fbe1b10" dependencies = [ "futures-core", - "futures-sink", ] [[package]] name = "futures-core" -version = "0.3.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "098cd1c6dda6ca01650f1a37a794245eb73181d0d4d4e955e2f3c37db7af1815" - -[[package]] -name = "futures-cpupool" -version = "0.1.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ab90cde24b3319636588d0c35fe03b1333857621051837ed769faefb4c2162e4" -dependencies = [ - "futures 0.1.31", - "num_cpus", -] - -[[package]] -name = "futures-executor" -version = "0.3.14" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "10f6cb7042eda00f0049b1d2080aa4b93442997ee507eb3828e8bd7577f94c9d" -dependencies = [ - "futures-core", - "futures-task", - "futures-util", -] +checksum = "05f29059c0c2090612e8d742178b0580d2dc940c837851ad723096f87af6663e" [[package]] name = "futures-io" -version = "0.3.14" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "365a1a1fb30ea1c03a830fdb2158f5236833ac81fa0ad12fe35b29cddc35cb04" +checksum = "9e5c1b78ca4aae1ac06c48a526a655760685149f0d465d21f37abfe57ce075c6" [[package]] name = "futures-macro" -version = "0.3.14" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "668c6733a182cd7deb4f1de7ba3bf2120823835b3bcfbeacf7d2c4a773c1bb8b" +checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650" dependencies = [ - "proc-macro-hack", "proc-macro2", "quote", "syn", @@ -759,163 +724,159 @@ dependencies = [ [[package]] name = "futures-sink" -version = "0.3.14" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c5629433c555de3d82861a7a4e3794a4c40040390907cfbfd7143a92a426c23" +checksum = "e575fab7d1e0dcb8d0c7bcf9a63ee213816ab51902e6d244a95819acacf1d4f7" [[package]] name = "futures-task" -version = "0.3.14" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba7aa51095076f3ba6d9a1f702f74bd05ec65f555d70d2033d55ba8d69f581bc" +checksum = "f90f7dce0722e95104fcb095585910c0977252f286e354b5e3bd38902cd99988" [[package]] name = "futures-util" -version = "0.3.14" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c144ad54d60f23927f0a6b6d816e4271278b64f005ad65e4e35291d2de9c025" +checksum = "9fa08315bb612088cc391249efdc3bc77536f16c91f6cf495e6fbe85b20a4a81" dependencies = [ - "futures-channel", "futures-core", "futures-io", "futures-macro", - "futures-sink", "futures-task", "memchr", - "pin-project-lite 0.2.6", + "pin-project-lite", "pin-utils", - "proc-macro-hack", - "proc-macro-nested", "slab", ] [[package]] name = "generic-array" -version = "0.12.4" +version = "0.14.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ffdf9f34f1447443d37393cc6c2b8313aebddcd96906caf34e54c68d8e57d7bd" +checksum = "4bb6743198531e02858aeaea5398fcc883e71851fcbcb5a2f773e2fb6cb1edf2" dependencies = [ "typenum", + "version_check", ] [[package]] name = "getrandom" -version = "0.1.16" +version = "0.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8fc3cb4d91f53b50155bdcfd23f6a4c39ae1969c2ae85982b135750cccaf5fce" +checksum = "335ff9f135e4384c8150d6f27c6daed433577f86b4750418338c01a1a2528592" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", "libc", - "wasi 0.9.0+wasi-snapshot-preview1", + "wasi", ] [[package]] name = "getrandom" -version = "0.2.2" +version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c9495705279e7140bf035dde1f6e750c162df8b625267cd52cc44e0b156732c8" +checksum = "899def5c37c4fd7b2664648c28120ecec138e4d395b459e5ca34f9cce2dd77fd" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", "libc", - "wasi 0.10.2+wasi-snapshot-preview1", + "r-efi", + "wasip2", ] -[[package]] -name = "gimli" -version = "0.24.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0e4075386626662786ddb0ec9081e7c7eeb1ba31951f447ca780ef9f5d568189" - [[package]] name = "glob" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b919933a397b79c37e33b77bb2aa3dc8eb6e165ad809e58ff75bc7db2e34574" - -[[package]] -name = "h2" -version = "0.1.26" +version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a5b34c246847f938a410a03c5458c7fee2274436675e76d8b903c08efc29c462" -dependencies = [ - "byteorder", - "bytes 0.4.12", - "fnv", - "futures 0.1.31", - "http 0.1.21", - "indexmap", - "log", - "slab", - "string", - "tokio-io", -] +checksum = "0cc23270f6e1808e30a928bdc84dea0b9b4136a8bc82338574f23baf47bbd280" [[package]] name = "h2" -version = "0.2.7" +version = "0.3.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5e4728fd124914ad25e99e3d15a9361a879f6620f63cb56bbb08f95abb97a535" +checksum = "0beca50380b1fc32983fc1cb4587bfa4bb9e78fc259aad4a0032d2080309222d" dependencies = [ - "bytes 0.5.6", + "bytes", "fnv", "futures-core", "futures-sink", "futures-util", - "http 0.2.4", - "indexmap", + "http 0.2.12", + "indexmap 2.12.0", "slab", - "tokio 0.2.25", + "tokio", "tokio-util", "tracing", - "tracing-futures", ] [[package]] name = "handlebars" -version = "3.5.5" +version = "6.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4498fc115fa7d34de968184e473529abb40eeb6be8bc5f7faba3d08c316cb3e3" +checksum = "759e2d5aea3287cb1190c8ec394f42866cb5bf74fcbf213f354e3c856ea26098" dependencies = [ + "derive_builder", "log", + "num-order", "pest", "pest_derive", - "quick-error 2.0.1", "serde", "serde_json", + "thiserror", ] [[package]] name = "hashbrown" -version = "0.9.1" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" + +[[package]] +name = "hashbrown" +version = "0.15.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d7afe4a420e3fe79967a00898cc1f4db7c8a49a9333a29f8a4bd76a253d5cd04" +checksum = "9229cfe53dfd69f0609a49f65461bd93001ea1ef889cd5529dd176593f5338a1" +dependencies = [ + "foldhash", +] + +[[package]] +name = "hashbrown" +version = "0.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5419bdc4f6a9207fbeba6d11b604d481addf78ecd10c11ad51e76c2f6482748d" [[package]] name = "hashicorp_vault" -version = "1.1.0" +version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ece669ffcef7f75a77651a6a7c7dfd4efb21bfdbf3a4d5fae3a45576fa7468dc" +checksum = "55d829f72fad7263fada3eb758f6ee9af60132c425e470c6a4af45a6cafab16d" dependencies = [ - "base64 0.12.3", + "base64 0.13.1", "chrono", "log", - "quick-error 1.2.3", + "quick-error", "reqwest", "serde", "serde_derive", "serde_json", - "url 1.7.2", + "url", ] [[package]] -name = "hermit-abi" -version = "0.1.18" +name = "hashlink" +version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "322f4de77956e22ed0e5032c359a0f1273f1f7f0d79bfa3b8ffbc730d7fbcc5c" +checksum = "7382cf6263419f2d8df38c55d7da83da5c18aef87fc7a7fc1fb1e344edfe14c1" dependencies = [ - "libc", + "hashbrown 0.15.5", ] +[[package]] +name = "heck" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" + [[package]] name = "hex" version = "0.4.3" @@ -924,592 +885,629 @@ checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" [[package]] name = "http" -version = "0.1.21" +version = "0.2.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d6ccf5ede3a895d8856620237b2f02972c1bbc78d2965ad7fe8838d4a0ed41f0" +checksum = "601cbb57e577e2f5ef5be8e7b83f0f63994f25aa94d673e54a92d5c516d101f1" dependencies = [ - "bytes 0.4.12", + "bytes", "fnv", "itoa", ] [[package]] name = "http" -version = "0.2.4" +version = "1.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "527e8c9ac747e28542699a951517aa9a6945af506cd1f2e1b53a576c17b6cc11" +checksum = "f4a85d31aea989eead29a3aaf9e1115a180df8282431156e533de47660892565" dependencies = [ - "bytes 1.0.1", + "bytes", "fnv", "itoa", ] [[package]] name = "http-body" -version = "0.1.0" +version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6741c859c1b2463a423a1dbce98d418e6c3c3fc720fb0d45528657320920292d" +checksum = "7ceab25649e9960c0311ea418d17bee82c0dcec1bd053b5f9a66e265a693bed2" dependencies = [ - "bytes 0.4.12", - "futures 0.1.31", - "http 0.1.21", - "tokio-buf", + "bytes", + "http 0.2.12", + "pin-project-lite", ] [[package]] name = "http-body" -version = "0.3.1" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "13d5ff830006f7646652e057693569bfe0d51760c0085a071769d142a205111b" +checksum = "1efedce1fb8e6913f23e0c92de8e62cd5b772a67e7b3946df930a62566c93184" dependencies = [ - "bytes 0.5.6", - "http 0.2.4", + "bytes", + "http 1.3.1", ] [[package]] -name = "httparse" -version = "1.4.0" +name = "http-body-util" +version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4a1ce40d6fc9764887c2fdc7305c3dcc429ba11ff981c1509416afd5697e4437" +checksum = "b021d93e26becf5dc7e1b75b1bed1fd93124b374ceb73f43d4d4eafec896a64a" +dependencies = [ + "bytes", + "futures-core", + "http 1.3.1", + "http-body 1.0.1", + "pin-project-lite", +] [[package]] -name = "httpdate" -version = "0.3.2" +name = "httparse" +version = "1.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "494b4d60369511e7dea41cf646832512a94e542f68bb9c49e54518e0f468eb47" +checksum = "6dbf3de79e51f3d586ab4cb9d5c3e2c14aa28ed23d180cf89b4df0454a69cc87" [[package]] -name = "humantime" -version = "1.3.0" +name = "httpdate" +version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "df004cfca50ef23c36850aaaa59ad52cc70d0e90243c3c7737a4dd32dc7a3c4f" -dependencies = [ - "quick-error 1.2.3", -] +checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9" [[package]] name = "hyper" -version = "0.12.36" +version = "0.14.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c843caf6296fc1f93444735205af9ed4e109a539005abb2564ae1d6fad34c52" +checksum = "41dfc780fdec9373c01bae43289ea34c972e40ee3c9f6b3c8801a35f35586ce7" dependencies = [ - "bytes 0.4.12", - "futures 0.1.31", - "futures-cpupool", - "h2 0.1.26", - "http 0.1.21", - "http-body 0.1.0", + "bytes", + "futures-channel", + "futures-core", + "futures-util", + "h2", + "http 0.2.12", + "http-body 0.4.6", "httparse", - "iovec", + "httpdate", "itoa", - "log", - "net2", - "rustc_version", - "time", - "tokio 0.1.22", - "tokio-buf", - "tokio-executor", - "tokio-io", - "tokio-reactor", - "tokio-tcp", - "tokio-threadpool", - "tokio-timer", - "want 0.2.0", + "pin-project-lite", + "socket2 0.5.10", + "tokio", + "tower-service", + "tracing", + "want", ] [[package]] name = "hyper" -version = "0.13.10" +version = "1.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a6f157065790a3ed2f88679250419b5cdd96e714a0d65f7797fd337186e96bb" +checksum = "eb3aa54a13a0dfe7fbe3a59e0c76093041720fdc77b110cc0fc260fafb4dc51e" dependencies = [ - "bytes 0.5.6", + "atomic-waker", + "bytes", "futures-channel", "futures-core", - "futures-util", - "h2 0.2.7", - "http 0.2.4", - "http-body 0.3.1", + "http 1.3.1", + "http-body 1.0.1", "httparse", "httpdate", "itoa", - "pin-project 1.0.7", - "socket2", - "tokio 0.2.25", - "tower-service", - "tracing", - "want 0.3.0", + "pin-project-lite", + "pin-utils", + "smallvec", + "tokio", + "want", ] [[package]] -name = "hyper-rustls" -version = "0.20.0" +name = "hyper-named-pipe" +version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac965ea399ec3a25ac7d13b8affd4b8f39325cca00858ddf5eb29b79e6b14b08" +checksum = "73b7d8abf35697b81a825e386fc151e0d503e8cb5fcb93cc8669c376dfd6f278" dependencies = [ - "bytes 0.5.6", - "ct-logs", - "futures-util", - "hyper 0.13.10", - "log", - "rustls", - "rustls-native-certs", - "tokio 0.2.25", - "tokio-rustls", - "webpki", + "hex", + "hyper 1.7.0", + "hyper-util", + "pin-project-lite", + "tokio", + "tower-service", + "winapi", ] [[package]] name = "hyper-tls" -version = "0.3.2" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3a800d6aa50af4b5850b2b0f659625ce9504df908e9733b635720483be26174f" +checksum = "d6183ddfa99b85da61a140bea0efc93fdf56ceaa041b37d553518030827f9905" dependencies = [ - "bytes 0.4.12", - "futures 0.1.31", - "hyper 0.12.36", + "bytes", + "hyper 0.14.32", "native-tls", - "tokio-io", + "tokio", + "tokio-native-tls", ] [[package]] -name = "hyperlocal" -version = "0.7.0" +name = "hyper-util" +version = "0.1.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f192a5a791c0781b93e69f60a652eb6ae9331f77b9efe90c9827a75df5141a9b" +checksum = "3c6995591a8f1380fcb4ba966a252a4b29188d51d2b89e3a252f5305be65aea8" dependencies = [ + "bytes", + "futures-channel", + "futures-core", "futures-util", - "hex", - "hyper 0.13.10", - "pin-project 0.4.28", - "tokio 0.2.25", + "http 1.3.1", + "http-body 1.0.1", + "hyper 1.7.0", + "libc", + "pin-project-lite", + "socket2 0.6.1", + "tokio", + "tower-service", + "tracing", ] [[package]] -name = "idna" -version = "0.1.5" +name = "hyperlocal" +version = "0.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38f09e0f0b1fb55fdee1f17470ad800da77af5186a1a76c026b679358b7e844e" +checksum = "986c5ce3b994526b3cd75578e62554abd09f0899d6206de48b3e96ab34ccc8c7" dependencies = [ - "matches", - "unicode-bidi", - "unicode-normalization", + "hex", + "http-body-util", + "hyper 1.7.0", + "hyper-util", + "pin-project-lite", + "tokio", + "tower-service", ] [[package]] -name = "idna" -version = "0.2.3" +name = "iana-time-zone" +version = "0.1.64" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "418a0a6fab821475f634efe3ccc45c013f742efe03d853e8d3355d5cb850ecf8" +checksum = "33e57f83510bb73707521ebaffa789ec8caf86f9657cad665b092b581d40e9fb" dependencies = [ - "matches", - "unicode-bidi", - "unicode-normalization", + "android_system_properties", + "core-foundation-sys", + "iana-time-zone-haiku", + "js-sys", + "log", + "wasm-bindgen", + "windows-core", ] [[package]] -name = "include_dir" -version = "0.6.0" +name = "iana-time-zone-haiku" +version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "23d58bdeb22b1c4691106c084b1063781904c35d0f22eda2a283598968eac61a" +checksum = "f31827a206f56af32e590ba56d5d2d085f558508192593743f16b2306495269f" dependencies = [ - "glob", - "include_dir_impl", - "proc-macro-hack", + "cc", ] [[package]] -name = "include_dir_impl" -version = "0.6.0" +name = "icu_collections" +version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "327869970574819d24d1dca25c891856144d29159ab797fa9dc725c5c3f57215" +checksum = "4c6b649701667bbe825c3b7e6388cb521c23d88644678e83c0c4d0a621a34b43" dependencies = [ - "anyhow", - "proc-macro-hack", - "proc-macro2", - "quote", - "syn", + "displaydoc", + "potential_utf", + "yoke", + "zerofrom", + "zerovec", ] [[package]] -name = "indexmap" -version = "1.6.2" +name = "icu_locale_core" +version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "824845a0bf897a9042383849b02c1bc219c2383772efcd5c6f9766fa4b81aef3" +checksum = "edba7861004dd3714265b4db54a3c390e880ab658fec5f7db895fae2046b5bb6" dependencies = [ - "autocfg 1.0.1", - "hashbrown", + "displaydoc", + "litemap", + "tinystr", + "writeable", + "zerovec", ] [[package]] -name = "iovec" -version = "0.1.4" +name = "icu_normalizer" +version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b2b3ea6ff95e175473f8ffe6a7eb7c00d054240321b84c57051175fe3c1e075e" +checksum = "5f6c8828b67bf8908d82127b2054ea1b4427ff0230ee9141c54251934ab1b599" dependencies = [ - "libc", + "icu_collections", + "icu_normalizer_data", + "icu_properties", + "icu_provider", + "smallvec", + "zerovec", ] [[package]] -name = "itertools" -version = "0.9.0" +name = "icu_normalizer_data" +version = "2.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7aedcccd01fc5fe81e6b489c15b247b8b0690feb23304303a9e560f37efc560a" + +[[package]] +name = "icu_properties" +version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "284f18f85651fe11e8a991b2adb42cb078325c996ed026d994719efcfca1d54b" +checksum = "e93fcd3157766c0c8da2f8cff6ce651a31f0810eaa1c51ec363ef790bbb5fb99" dependencies = [ - "either", + "icu_collections", + "icu_locale_core", + "icu_properties_data", + "icu_provider", + "zerotrie", + "zerovec", ] [[package]] -name = "itoa" -version = "0.4.7" +name = "icu_properties_data" +version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd25036021b0de88a0aff6b850051563c6516d0bf53f8638938edbb9de732736" +checksum = "02845b3647bb045f1100ecd6480ff52f34c35f82d9880e029d329c21d1054899" [[package]] -name = "js-sys" -version = "0.3.51" +name = "icu_provider" +version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "83bdfbace3a0e81a4253f73b49e960b053e396a11012cbd49b9b74d6a2b67062" +checksum = "85962cf0ce02e1e0a629cc34e7ca3e373ce20dda4c4d7294bbd0bf1fdb59e614" dependencies = [ - "wasm-bindgen", + "displaydoc", + "icu_locale_core", + "writeable", + "yoke", + "zerofrom", + "zerotrie", + "zerovec", ] [[package]] -name = "json-pointer" -version = "0.3.4" +name = "ident_case" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5fe841b94e719a482213cee19dd04927cf412f26d8dc84c5a446c081e49c2997" -dependencies = [ - "serde_json", -] +checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" [[package]] -name = "jsonway" -version = "2.0.0" +name = "idna" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "effcb749443c905fbaef49d214f8b1049c240e0adb7af9baa0e201e625e4f9de" +checksum = "3b0875f23caa03898994f6ddc501886a45c7d3d62d04d2d90788d47be1b1e4de" dependencies = [ - "serde", - "serde_json", + "idna_adapter", + "smallvec", + "utf8_iter", ] [[package]] -name = "kernel32-sys" -version = "0.2.2" +name = "idna_adapter" +version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d" +checksum = "3acae9609540aa318d1bc588455225fb2085b9ed0c4f6bd0d9d5bcd86f1a0344" dependencies = [ - "winapi 0.2.8", - "winapi-build", + "icu_normalizer", + "icu_properties", ] [[package]] -name = "lazy_static" -version = "1.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" - -[[package]] -name = "libc" -version = "0.2.94" +name = "include_dir" +version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "18794a8ad5b29321f790b55d93dfba91e125cb1a9edbd4f8e3150acc771c1a5e" +checksum = "923d117408f1e49d914f1a379a309cffe4f18c05cf4e3d12e613a15fc81bd0dd" +dependencies = [ + "include_dir_macros", +] [[package]] -name = "linked-hash-map" -version = "0.5.4" +name = "include_dir_macros" +version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7fb9b38af92608140b86b693604b9ffcc5824240a484d1ecd4795bacb2fe88f3" +checksum = "7cab85a7ed0bd5f0e76d93846e0147172bed2e2d3f859bcc33a8d9699cad1a75" +dependencies = [ + "proc-macro2", + "quote", +] [[package]] -name = "lock_api" -version = "0.3.4" +name = "indexmap" +version = "1.9.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c4da24a77a3d8a6d4862d95f72e6fdb9c09a643ecdb402d754004a557f2bec75" +checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99" dependencies = [ - "scopeguard", + "autocfg", + "hashbrown 0.12.3", + "serde", ] [[package]] -name = "log" -version = "0.4.14" +name = "indexmap" +version = "2.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "51b9bbe6c47d51fc3e1a9b945965946b4c44142ab8792c50835a980d362c2710" +checksum = "6717a8d2a5a929a1a2eb43a12812498ed141a0bcfb7e8f7844fbdbe4303bba9f" dependencies = [ - "cfg-if 1.0.0", + "equivalent", + "hashbrown 0.16.0", + "serde", + "serde_core", ] [[package]] -name = "maplit" -version = "1.0.2" +name = "ipnet" +version = "2.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3e2e65a1a2e43cfcb47a895c4c8b10d1f4a61097f9f254f183aee60cad9c651d" +checksum = "469fb0b9cefa57e3ef31275ee7cacb78f2fdca44e4765491884a2b119d4eb130" [[package]] -name = "matches" -version = "0.1.8" +name = "is_terminal_polyfill" +version = "1.70.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ffc5c5338469d4d3ea17d269fa8ea3512ad247247c30bd2df69e68309ed0a08" +checksum = "a6cb138bb79a146c1bd460005623e142ef0181e3d0219cb493e02f7d08a35695" [[package]] -name = "maybe-uninit" -version = "2.0.0" +name = "itertools" +version = "0.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "60302e4db3a61da70c0cb7991976248362f30319e88850c487b9b95bbf059e00" +checksum = "2b192c782037fadd9cfa75548310488aabdbf3d2da73885b31bd0abd03351285" +dependencies = [ + "either", +] [[package]] -name = "memchr" -version = "2.4.0" +name = "itoa" +version = "1.0.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b16bd47d9e329435e309c58469fe0791c2d0d1ba96ec0954152a5ae2b04387dc" +checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c" [[package]] -name = "memoffset" -version = "0.5.6" +name = "jiff" +version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "043175f069eda7b85febe4a74abbaeff828d9f8b448515d3151a14a3542811aa" +checksum = "be1f93b8b1eb69c77f24bbb0afdf66f54b632ee39af40ca21c4365a1d7347e49" dependencies = [ - "autocfg 1.0.1", + "jiff-static", + "log", + "portable-atomic", + "portable-atomic-util", + "serde", ] [[package]] -name = "memoffset" -version = "0.6.3" +name = "jiff-static" +version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f83fb6581e8ed1f85fd45c116db8405483899489e38406156c25eb743554361d" +checksum = "03343451ff899767262ec32146f6d559dd759fdadf42ff0e227c7c48f72594b4" dependencies = [ - "autocfg 1.0.1", + "proc-macro2", + "quote", + "syn", ] [[package]] -name = "mime" -version = "0.3.16" +name = "js-sys" +version = "0.3.82" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2a60c7ce501c71e03a9c9c0d35b861413ae925bd979cc7a4e30d060069aaac8d" +checksum = "b011eec8cc36da2aab2d5cff675ec18454fad408585853910a202391cf9f8e65" +dependencies = [ + "once_cell", + "wasm-bindgen", +] [[package]] -name = "mime_guess" -version = "2.0.3" +name = "json-pointer" +version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2684d4c2e97d99848d30b324b00c8fcc7e5c897b7cbb5819b09e7c90e8baf212" +checksum = "5fe841b94e719a482213cee19dd04927cf412f26d8dc84c5a446c081e49c2997" dependencies = [ - "mime", - "unicase", + "serde_json", ] [[package]] -name = "miniz_oxide" -version = "0.4.4" +name = "jsonway" +version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a92518e98c078586bc6c934028adcca4c92a53d6a958196de835170a01d84e4b" +checksum = "effcb749443c905fbaef49d214f8b1049c240e0adb7af9baa0e201e625e4f9de" dependencies = [ - "adler", - "autocfg 1.0.1", + "serde", + "serde_json", ] [[package]] -name = "mio" -version = "0.6.23" +name = "lazy_static" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4afd66f5b91bf2a3bc13fad0e21caedac168ca4c707504e75585648ae80e4cc4" -dependencies = [ - "cfg-if 0.1.10", - "fuchsia-zircon", - "fuchsia-zircon-sys", - "iovec", - "kernel32-sys", - "libc", - "log", - "miow", - "net2", - "slab", - "winapi 0.2.8", -] +checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" [[package]] -name = "mio-uds" -version = "0.6.8" +name = "libc" +version = "0.2.177" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "afcb699eb26d4332647cc848492bbc15eafb26f08d0304550d5aa1f612e066f0" -dependencies = [ - "iovec", - "libc", - "mio", -] +checksum = "2874a2af47a2325c2001a6e6fad9b16a53b802102b528163885171cf92b15976" [[package]] -name = "miow" -version = "0.2.2" +name = "libredox" +version = "0.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ebd808424166322d4a38da87083bfddd3ac4c131334ed55856112eb06d46944d" +checksum = "416f7e718bdb06000964960ffa43b4335ad4012ae8b99060261aa4a8088d5ccb" dependencies = [ - "kernel32-sys", - "net2", - "winapi 0.2.8", - "ws2_32-sys", + "bitflags 2.10.0", + "libc", ] [[package]] -name = "native-tls" -version = "0.2.7" +name = "linux-raw-sys" +version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b8d96b2e1c8da3957d58100b09f102c6d9cfdfced01b7ec5a8974044bb09dbd4" -dependencies = [ - "lazy_static", +checksum = "df1d3c3b53da64cf5760482273a98e575c651a67eec7f77df96b5b642de8f039" + +[[package]] +name = "litemap" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6373607a59f0be73a39b6fe456b8192fcc3585f602af20751600e974dd455e77" + +[[package]] +name = "log" +version = "0.4.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34080505efa8e45a4b816c349525ebe327ceaa8559756f0356cba97ef3bf7432" + +[[package]] +name = "memchr" +version = "2.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f52b00d39961fc5b2736ea853c9cc86238e165017a493d1d5c8eac6bdc4cc273" + +[[package]] +name = "mime" +version = "0.3.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a" + +[[package]] +name = "mio" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "69d83b0086dc8ecf3ce9ae2874b2d1290252e2a30720bea58a5c6639b0092873" +dependencies = [ + "libc", + "wasi", + "windows-sys 0.61.2", +] + +[[package]] +name = "native-tls" +version = "0.2.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87de3442987e9dbec73158d5c715e7ad9072fda936bb03d19d7fa10e00520f0e" +dependencies = [ "libc", "log", "openssl", "openssl-probe", "openssl-sys", "schannel", - "security-framework 2.2.0", - "security-framework-sys 2.2.0", + "security-framework", + "security-framework-sys", "tempfile", ] [[package]] -name = "net2" -version = "0.2.37" +name = "num-conv" +version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "391630d12b68002ae1e25e8f974306474966550ad82dac6886fb8910c19568ae" -dependencies = [ - "cfg-if 0.1.10", - "libc", - "winapi 0.3.9", -] +checksum = "51d515d32fb182ee37cda2ccdcb92950d6a3c2893aa280e540671c2cd0f3b1d9" [[package]] -name = "num-integer" -version = "0.1.44" +name = "num-modular" +version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d2cc698a63b549a70bc047073d2949cce27cd1c7b0a4a862d08a8031bc2801db" -dependencies = [ - "autocfg 1.0.1", - "num-traits", -] +checksum = "17bb261bf36fa7d83f4c294f834e91256769097b3cb505d44831e0a179ac647f" [[package]] -name = "num-traits" -version = "0.2.14" +name = "num-order" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a64b1ec5cda2586e284722486d802acf1f7dbdc623e2bfc57e65ca1cd099290" +checksum = "537b596b97c40fcf8056d153049eb22f481c17ebce72a513ec9286e4986d1bb6" dependencies = [ - "autocfg 1.0.1", + "num-modular", ] [[package]] -name = "num_cpus" -version = "1.13.0" +name = "num-traits" +version = "0.2.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05499f3756671c15885fee9034446956fff3f243d6077b91e5767df161f766b3" +checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" dependencies = [ - "hermit-abi", - "libc", + "autocfg", ] -[[package]] -name = "object" -version = "0.24.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a5b3dd1c072ee7963717671d1ca129f1048fda25edea6b752bfc71ac8854170" - [[package]] name = "once_cell" -version = "1.7.2" +version = "1.21.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af8b08b04175473088b46763e51ee54da5f9a164bc162f615b91bc179dbf15a3" +checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d" [[package]] -name = "opaque-debug" -version = "0.2.3" +name = "once_cell_polyfill" +version = "1.70.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2839e79665f131bdb5782e51f2c6c9599c133c6098982a54c794358bf432529c" +checksum = "384b8ab6d37215f3c5301a95a4accb5d64aa607f1fcb26a11b5303878451b4fe" [[package]] name = "openssl" -version = "0.10.34" +version = "0.10.74" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d7830286ad6a3973c0f1d9b73738f69c76b739301d0229c4b96501695cbe4c8" +checksum = "24ad14dd45412269e1a30f52ad8f0664f0f4f4a89ee8fe28c3b3527021ebb654" dependencies = [ - "bitflags", - "cfg-if 1.0.0", + "bitflags 2.10.0", + "cfg-if", "foreign-types", "libc", "once_cell", + "openssl-macros", "openssl-sys", ] [[package]] -name = "openssl-probe" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77af24da69f9d9341038eba93a073b1fdaaa1b788221b00a69bce9e762cb32de" - -[[package]] -name = "openssl-sys" -version = "0.9.63" +name = "openssl-macros" +version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6b0d6fb7d80f877617dfcb014e605e2b5ab2fb0afdf27935219bb6bd984cb98" +checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" dependencies = [ - "autocfg 1.0.1", - "cc", - "libc", - "pkg-config", - "vcpkg", + "proc-macro2", + "quote", + "syn", ] [[package]] -name = "parking_lot" -version = "0.9.0" +name = "openssl-probe" +version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f842b1982eb6c2fe34036a4fbfb06dd185a3f5c8edfaacdf7d1ea10b07de6252" -dependencies = [ - "lock_api", - "parking_lot_core", - "rustc_version", -] +checksum = "d05e27ee213611ffe7d6348b942e8f942b37114c00cc03cec254295a4a17852e" [[package]] -name = "parking_lot_core" -version = "0.6.2" +name = "openssl-sys" +version = "0.9.110" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b876b1b9e7ac6e1a74a6da34d25c42e17e8862aa409cbbbdcfc8d86c6f3bc62b" +checksum = "0a9f0075ba3c21b09f8e8b2026584b1d18d49388648f2fbbf3c97ea8deced8e2" dependencies = [ - "cfg-if 0.1.10", - "cloudabi", + "cc", "libc", - "redox_syscall 0.1.57", - "rustc_version", - "smallvec", - "winapi 0.3.9", + "pkg-config", + "vcpkg", ] [[package]] -name = "percent-encoding" -version = "1.0.1" +name = "option-ext" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "31010dd2e1ac33d5b46a5b413495239882813e0369f8ed8a5e266f173602f831" +checksum = "04744f49eae99ab78e0d5c0b603ab218f515ea8cfe5a456d7629ad883a3b6e7d" [[package]] name = "percent-encoding" -version = "2.1.0" +version = "2.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d4fd5641d01c8f18a23da7b6fe29298ff4b55afcccdf78973b24cf3175fee32e" +checksum = "9b4f627cb1b25917193a259e49bdad08f671f8d9708acfd5fe0a8c1455d87220" [[package]] name = "pest" -version = "2.1.3" +version = "2.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "10f4872ae94d7b90ae48754df22fd42ad52ce740b8f370b03da4835417403e53" +checksum = "989e7521a040efde50c3ab6bbadafbe15ab6dc042686926be59ac35d74607df4" dependencies = [ + "memchr", "ucd-trie", ] [[package]] name = "pest_derive" -version = "2.1.0" +version = "2.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "833d1ae558dc601e9a60366421196a8d94bc0ac980476d0b67e1d0988d72b2d0" +checksum = "187da9a3030dbafabbbfb20cb323b976dc7b7ce91fcd84f2f74d6e31d378e2de" dependencies = [ "pest", "pest_generator", @@ -1517,9 +1515,9 @@ dependencies = [ [[package]] name = "pest_generator" -version = "2.1.3" +version = "2.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "99b8db626e31e5b81787b9783425769681b347011cc59471e33ea46d2ea0cf55" +checksum = "49b401d98f5757ebe97a26085998d6c0eecec4995cad6ab7fc30ffdf4b052843" dependencies = [ "pest", "pest_meta", @@ -1530,29 +1528,28 @@ dependencies = [ [[package]] name = "pest_meta" -version = "2.1.3" +version = "2.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "54be6e404f5317079812fc8f9f5279de376d8856929e21c184ecf6bbd692a11d" +checksum = "72f27a2cfee9f9039c4d86faa5af122a0ac3851441a34865b8a043b46be0065a" dependencies = [ - "maplit", "pest", - "sha-1", + "sha2", ] [[package]] name = "phf" -version = "0.8.0" +version = "0.11.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3dfb61232e34fcb633f43d12c58f83c1df82962dcdfa565a4e866ffc17dafe12" +checksum = "1fd6780a80ae0c52cc120a26a1a42c1ae51b247a253e4e06113d23d2c2edd078" dependencies = [ "phf_shared", ] [[package]] name = "phf_codegen" -version = "0.8.0" +version = "0.11.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cbffee61585b0411840d3ece935cce9cb6321f01c45477d30066498cd5e1a815" +checksum = "aef8048c789fa5e851558d709946d6d79a8ff88c0440c587967f8e94bfb1216a" dependencies = [ "phf_generator", "phf_shared", @@ -1560,129 +1557,103 @@ dependencies = [ [[package]] name = "phf_generator" -version = "0.8.0" +version = "0.11.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "17367f0cc86f2d25802b2c26ee58a7b23faeccf78a396094c13dced0d0182526" +checksum = "3c80231409c20246a13fddb31776fb942c38553c51e871f8cbd687a4cfb5843d" dependencies = [ "phf_shared", - "rand 0.7.3", + "rand 0.8.5", ] [[package]] name = "phf_shared" -version = "0.8.0" +version = "0.11.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c00cf8b9eafe68dde5e9eaa2cef8ee84a9336a47d566ec55ca16589633b65af7" +checksum = "67eabc2ef2a60eb7faa00097bd1ffdb5bd28e62bf39990626a582201b7a754e5" dependencies = [ "siphasher", ] [[package]] -name = "pin-project" -version = "0.4.28" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "918192b5c59119d51e0cd221f4d49dde9112824ba717369e903c97d076083d0f" -dependencies = [ - "pin-project-internal 0.4.28", -] - -[[package]] -name = "pin-project" -version = "1.0.7" +name = "pin-project-lite" +version = "0.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c7509cc106041c40a4518d2af7a61530e1eed0e6285296a3d8c5472806ccc4a4" -dependencies = [ - "pin-project-internal 1.0.7", -] +checksum = "3b3cff922bd51709b605d9ead9aa71031d81447142d828eb4a6eba76fe619f9b" [[package]] -name = "pin-project-internal" -version = "0.4.28" +name = "pin-utils" +version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3be26700300be6d9d23264c73211d8190e755b6b5ca7a1b28230025511b52a5e" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] +checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" [[package]] -name = "pin-project-internal" -version = "1.0.7" +name = "pkg-config" +version = "0.3.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "48c950132583b500556b1efd71d45b319029f2b71518d979fcc208e16b42426f" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] +checksum = "7edddbd0b52d732b21ad9a5fab5c704c14cd949e5e9a1ec5929a24fded1b904c" [[package]] -name = "pin-project-lite" -version = "0.1.12" +name = "portable-atomic" +version = "1.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "257b64915a082f7811703966789728173279bdebb956b143dbcd23f6f970a777" +checksum = "f84267b20a16ea918e43c6a88433c2d54fa145c92a811b5b047ccbe153674483" [[package]] -name = "pin-project-lite" -version = "0.2.6" +name = "portable-atomic-util" +version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc0e1f259c92177c30a4c9d177246edd0a3568b25756a977d0632cf8fa37e905" +checksum = "d8a2f0d8d040d7848a709caf78912debcc3f33ee4b3cac47d73d1e1069e83507" +dependencies = [ + "portable-atomic", +] [[package]] -name = "pin-utils" -version = "0.1.0" +name = "potential_utf" +version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" +checksum = "b73949432f5e2a09657003c25bca5e19a0e9c84f8058ca374f49e0ebe605af77" +dependencies = [ + "zerovec", +] [[package]] -name = "pkg-config" -version = "0.3.19" +name = "powerfmt" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3831453b3449ceb48b6d9c7ad7c96d5ea673e9b470a1dc578c2ce6521230884c" +checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391" [[package]] name = "ppv-lite86" -version = "0.2.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac74c624d6b2d21f425f752262f42188365d7b8ff1aff74c82e45136510a4857" - -[[package]] -name = "proc-macro-hack" -version = "0.5.19" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dbf0c48bc1d91375ae5c3cd81e3722dff1abcf81a30960240640d223f59fe0e5" - -[[package]] -name = "proc-macro-nested" -version = "0.1.7" +version = "0.2.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bc881b2c22681370c6a780e47af9840ef841837bc98118431d4e1868bd0c1086" +checksum = "85eae3c4ed2f50dcfe72643da4befc30deadb458a9b590d720cde2f2b1e97da9" +dependencies = [ + "zerocopy", +] [[package]] name = "proc-macro2" -version = "1.0.26" +version = "1.0.103" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a152013215dca273577e18d2bf00fa862b89b24169fb78c4c95aeb07992c9cec" +checksum = "5ee95bc4ef87b8d5ba32e8b7714ccc834865276eab0aed5c9958d00ec45f49e8" dependencies = [ - "unicode-xid", + "unicode-ident", ] [[package]] -name = "publicsuffix" -version = "1.5.6" +name = "psl" +version = "2.1.155" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "95b4ce31ff0a27d93c8de1849cf58162283752f065a90d508f1105fa6c9a213f" +checksum = "dd6d2ec03a459f8b27aeb995fdbbdab4d00492b310c2a63b50b57b5bf1137613" dependencies = [ - "idna 0.2.3", - "url 2.2.2", + "psl-types", ] [[package]] -name = "quick-error" -version = "1.2.3" +name = "psl-types" +version = "2.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1d01941d82fa2ab50be1e79e6714289dd7cde78eba4c074bc5a4374f650dfe0" +checksum = "33cb294fe86a74cbcf50d4445b37da762029549ebeea341421c7c70370f86cac" [[package]] name = "quick-error" @@ -1692,509 +1663,537 @@ checksum = "a993555f31e5a609f617c12db6250dedcac1b0a85076912c436e6fc9b2c8e6a3" [[package]] name = "quote" -version = "1.0.9" +version = "1.0.41" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3d0b9745dc2debf507c8422de05d7226cc1f0644216dfdfead988f9b1ab32a7" +checksum = "ce25767e7b499d1b604768e7cde645d14cc8584231ea6b295e9c9eb22c02e1d1" dependencies = [ "proc-macro2", ] [[package]] -name = "rand" -version = "0.6.5" +name = "r-efi" +version = "5.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d71dacdc3c88c1fde3885a3be3fbab9f35724e6ce99467f7d9c5026132184ca" -dependencies = [ - "autocfg 0.1.7", - "libc", - "rand_chacha 0.1.1", - "rand_core 0.4.2", - "rand_hc 0.1.0", - "rand_isaac", - "rand_jitter", - "rand_os", - "rand_pcg 0.1.2", - "rand_xorshift", - "winapi 0.3.9", -] +checksum = "69cdb34c158ceb288df11e18b4bd39de994f6657d83847bdffdbd7f346754b0f" [[package]] name = "rand" -version = "0.7.3" +version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a6b1679d49b24bbfe0c803429aa1874472f50d9b363131f0e89fc356b544d03" +checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" dependencies = [ - "getrandom 0.1.16", - "libc", - "rand_chacha 0.2.2", - "rand_core 0.5.1", - "rand_hc 0.2.0", - "rand_pcg 0.2.1", + "rand_core 0.6.4", ] [[package]] name = "rand" -version = "0.8.3" +version = "0.9.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ef9e7e66b4468674bfcb0c81af8b7fa0bb154fa9f28eb840da5c447baeb8d7e" +checksum = "6db2770f06117d490610c7488547d543617b21bfa07796d7a12f6f1bd53850d1" dependencies = [ - "libc", - "rand_chacha 0.3.0", - "rand_core 0.6.2", - "rand_hc 0.3.0", + "rand_chacha", + "rand_core 0.9.3", ] [[package]] name = "rand_chacha" -version = "0.1.1" +version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "556d3a1ca6600bfcbab7c7c91ccb085ac7fbbcd70e008a98742e7847f4f7bcef" +checksum = "d3022b5f1df60f26e1ffddd6c66e8aa15de382ae63b3a0c1bfc0e4d3e3f325cb" dependencies = [ - "autocfg 0.1.7", - "rand_core 0.3.1", + "ppv-lite86", + "rand_core 0.9.3", ] [[package]] -name = "rand_chacha" -version = "0.2.2" +name = "rand_core" +version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f4c8ed856279c9737206bf725bf36935d8666ead7aa69b52be55af369d193402" -dependencies = [ - "ppv-lite86", - "rand_core 0.5.1", -] +checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" [[package]] -name = "rand_chacha" -version = "0.3.0" +name = "rand_core" +version = "0.9.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e12735cf05c9e10bf21534da50a147b924d555dc7a547c42e6bb2d5b6017ae0d" +checksum = "99d9a13982dcf210057a8a78572b2217b667c3beacbf3a0d8b454f6f82837d38" dependencies = [ - "ppv-lite86", - "rand_core 0.6.2", + "getrandom 0.3.4", ] [[package]] -name = "rand_core" -version = "0.3.1" +name = "rayon" +version = "1.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a6fdeb83b075e8266dcc8762c22776f6877a63111121f5f8c7411e5be7eed4b" +checksum = "368f01d005bf8fd9b1206fb6fa653e6c4a81ceb1466406b81792d87c5677a58f" dependencies = [ - "rand_core 0.4.2", + "either", + "rayon-core", ] [[package]] -name = "rand_core" -version = "0.4.2" +name = "rayon-core" +version = "1.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c33a3c44ca05fa6f1807d8e6743f3824e8509beca625669633be0acbdf509dc" +checksum = "22e18b0f0062d30d4230b2e85ff77fdfe4326feb054b9783a3460d8435c8ab91" +dependencies = [ + "crossbeam-deque", + "crossbeam-utils", +] [[package]] -name = "rand_core" -version = "0.5.1" +name = "redox_users" +version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "90bde5296fc891b0cef12a6d03ddccc162ce7b2aff54160af9338f8d40df6d19" +checksum = "a4e608c6638b9c18977b00b475ac1f28d14e84b27d8d42f70e0bf1e3dec127ac" dependencies = [ - "getrandom 0.1.16", + "getrandom 0.2.16", + "libredox", + "thiserror", ] [[package]] -name = "rand_core" -version = "0.6.2" +name = "ref-cast" +version = "1.0.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "34cf66eb183df1c5876e2dcf6b13d57340741e8dc255b48e40a26de954d06ae7" +checksum = "f354300ae66f76f1c85c5f84693f0ce81d747e2c3f21a45fef496d89c960bf7d" dependencies = [ - "getrandom 0.2.2", + "ref-cast-impl", ] [[package]] -name = "rand_hc" -version = "0.1.0" +name = "ref-cast-impl" +version = "1.0.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b40677c7be09ae76218dc623efbf7b18e34bced3f38883af07bb75630a21bc4" +checksum = "b7186006dcb21920990093f30e3dea63b7d6e977bf1256be20c3563a5db070da" dependencies = [ - "rand_core 0.3.1", + "proc-macro2", + "quote", + "syn", ] [[package]] -name = "rand_hc" -version = "0.2.0" +name = "regex" +version = "1.12.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca3129af7b92a17112d59ad498c6f81eaf463253766b90396d39ea7a39d6613c" +checksum = "843bc0191f75f3e22651ae5f1e72939ab2f72a4bc30fa80a066bd66edefc24d4" dependencies = [ - "rand_core 0.5.1", + "aho-corasick", + "memchr", + "regex-automata", + "regex-syntax", ] [[package]] -name = "rand_hc" -version = "0.3.0" +name = "regex-automata" +version = "0.4.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3190ef7066a446f2e7f42e239d161e905420ccab01eb967c9eb27d21b2322a73" +checksum = "5276caf25ac86c8d810222b3dbb938e512c55c6831a10f3e6ed1c93b84041f1c" dependencies = [ - "rand_core 0.6.2", + "aho-corasick", + "memchr", + "regex-syntax", ] [[package]] -name = "rand_isaac" -version = "0.1.1" +name = "regex-syntax" +version = "0.8.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a2d987857b319362043e95f5353c0535c1f58eec5336fdfcf626430af7def58" + +[[package]] +name = "reqwest" +version = "0.11.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ded997c9d5f13925be2a6fd7e66bf1872597f759fd9dd93513dd7e92e5a5ee08" +checksum = "dd67538700a17451e7cba03ac727fb961abb7607553461627b97de0b89cf4a62" dependencies = [ - "rand_core 0.3.1", + "base64 0.21.7", + "bytes", + "encoding_rs", + "futures-core", + "futures-util", + "h2", + "http 0.2.12", + "http-body 0.4.6", + "hyper 0.14.32", + "hyper-tls", + "ipnet", + "js-sys", + "log", + "mime", + "native-tls", + "once_cell", + "percent-encoding", + "pin-project-lite", + "rustls-pemfile", + "serde", + "serde_json", + "serde_urlencoded", + "sync_wrapper", + "system-configuration", + "tokio", + "tokio-native-tls", + "tower-service", + "url", + "wasm-bindgen", + "wasm-bindgen-futures", + "web-sys", + "winreg", ] [[package]] -name = "rand_jitter" -version = "0.1.4" +name = "retry" +version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1166d5c91dc97b88d1decc3285bb0a99ed84b05cfd0bc2341bdf2d43fc41e39b" +checksum = "a1e211f878258887b3e65dd3c8ff9f530fe109f441a117ee0cdc27f341355032" dependencies = [ - "libc", - "rand_core 0.4.2", - "winapi 0.3.9", + "rand 0.9.2", ] [[package]] -name = "rand_os" -version = "0.1.3" +name = "rustix" +version = "1.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b75f676a1e053fc562eafbb47838d67c84801e38fc1ba459e8f180deabd5071" +checksum = "cd15f8a2c5551a84d56efdc1cd049089e409ac19a3072d5037a17fd70719ff3e" dependencies = [ - "cloudabi", - "fuchsia-cprng", + "bitflags 2.10.0", + "errno", "libc", - "rand_core 0.4.2", - "rdrand", - "winapi 0.3.9", + "linux-raw-sys", + "windows-sys 0.61.2", ] [[package]] -name = "rand_pcg" -version = "0.1.2" +name = "rustls-pemfile" +version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "abf9b09b01790cfe0364f52bf32995ea3c39f4d2dd011eac241d2914146d0b44" +checksum = "1c74cae0a4cf6ccbbf5f359f08efdf8ee7e1dc532573bf0db71968cb56b1448c" dependencies = [ - "autocfg 0.1.7", - "rand_core 0.4.2", + "base64 0.21.7", ] [[package]] -name = "rand_pcg" -version = "0.2.1" +name = "rustversion" +version = "1.0.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "16abd0c1b639e9eb4d7c50c0b8100b0d0f849be2349829c740fe8e6eb4816429" -dependencies = [ - "rand_core 0.5.1", -] +checksum = "b39cdef0fa800fc44525c84ccb54a029961a8215f9619753635a9c0d2538d46d" [[package]] -name = "rand_xorshift" -version = "0.1.1" +name = "ryu" +version = "1.0.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cbf7e9e623549b0e21f6e97cf8ecf247c1a8fd2e8a992ae265314300b2455d5c" -dependencies = [ - "rand_core 0.3.1", -] +checksum = "28d3b2b1366ec20994f1fd18c3c594f05c5dd4bc44d8bb0c1c632c8d6829481f" [[package]] -name = "rayon" -version = "1.5.0" +name = "same-file" +version = "1.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b0d8e0819fadc20c74ea8373106ead0600e3a67ef1fe8da56e39b9ae7275674" +checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502" dependencies = [ - "autocfg 1.0.1", - "crossbeam-deque 0.8.0", - "either", - "rayon-core", + "winapi-util", ] [[package]] -name = "rayon-core" -version = "1.9.0" +name = "schannel" +version = "0.1.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ab346ac5921dc62ffa9f89b7a773907511cdfa5490c572ae9be1be33e8afa4a" +checksum = "891d81b926048e76efe18581bf793546b4c0eaf8448d72be8de2bbee5fd166e1" dependencies = [ - "crossbeam-channel", - "crossbeam-deque 0.8.0", - "crossbeam-utils 0.8.4", - "lazy_static", - "num_cpus", + "windows-sys 0.61.2", ] [[package]] -name = "rdrand" -version = "0.4.0" +name = "schemars" +version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "678054eb77286b51581ba43620cc911abf02758c91f93f479767aed0f90458b2" +checksum = "4cd191f9397d57d581cddd31014772520aa448f65ef991055d7f61582c65165f" dependencies = [ - "rand_core 0.3.1", + "dyn-clone", + "ref-cast", + "serde", + "serde_json", ] [[package]] -name = "redox_syscall" -version = "0.1.57" +name = "schemars" +version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "41cc0f7e4d5d4544e8861606a285bb08d3e70712ccc7d2b84d7c0ccfaf4b05ce" +checksum = "82d20c4491bc164fa2f6c5d44565947a52ad80b9505d8e36f8d54c27c739fcd0" +dependencies = [ + "dyn-clone", + "ref-cast", + "serde", + "serde_json", +] [[package]] -name = "redox_syscall" -version = "0.2.8" +name = "security-framework" +version = "2.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "742739e41cd49414de871ea5e549afb7e2a3ac77b589bcbebe8c82fab37147fc" +checksum = "897b2245f0b511c87893af39b033e5ca9cce68824c4d7e7630b5a1d339658d02" dependencies = [ - "bitflags", + "bitflags 2.10.0", + "core-foundation", + "core-foundation-sys", + "libc", + "security-framework-sys", ] [[package]] -name = "redox_users" -version = "0.4.0" +name = "security-framework-sys" +version = "2.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "528532f3d801c87aec9def2add9ca802fe569e44a544afe633765267840abe64" +checksum = "cc1f0cbffaac4852523ce30d8bd3c5cdc873501d96ff467ca09b6767bb8cd5c0" dependencies = [ - "getrandom 0.2.2", - "redox_syscall 0.2.8", + "core-foundation-sys", + "libc", ] [[package]] -name = "regex" -version = "1.5.4" +name = "semver" +version = "1.0.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d07a8629359eb56f1e2fb1652bb04212c072a87ba68546a04065d525673ac461" -dependencies = [ - "aho-corasick", - "memchr", - "regex-syntax", -] +checksum = "d767eb0aabc880b29956c35734170f26ed551a859dbd361d140cdbeca61ab1e2" [[package]] -name = "regex-syntax" -version = "0.6.25" +name = "serde" +version = "1.0.228" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f497285884f3fcff424ffc933e56d7cbca511def0c9831a7f9b5f6153e3cc89b" +checksum = "9a8e94ea7f378bd32cbbd37198a4a91436180c5bb472411e48b5ec2e2124ae9e" +dependencies = [ + "serde_core", + "serde_derive", +] [[package]] -name = "remove_dir_all" -version = "0.5.3" +name = "serde_core" +version = "1.0.228" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3acd125665422973a33ac9d3dd2df85edad0f4ae9b00dafb1a05e43a9f5ef8e7" +checksum = "41d385c7d4ca58e59fc732af25c3983b67ac852c1a25000afe1175de458b67ad" dependencies = [ - "winapi 0.3.9", + "serde_derive", ] [[package]] -name = "reqwest" -version = "0.9.24" +name = "serde_derive" +version = "1.0.228" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f88643aea3c1343c804950d7bf983bd2067f5ab59db6d613a08e05572f2714ab" +checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79" dependencies = [ - "base64 0.10.1", - "bytes 0.4.12", - "cookie", - "cookie_store", - "encoding_rs", - "flate2", - "futures 0.1.31", - "http 0.1.21", - "hyper 0.12.36", - "hyper-tls", - "log", - "mime", - "mime_guess", - "native-tls", - "serde", - "serde_json", - "serde_urlencoded", - "time", - "tokio 0.1.22", - "tokio-executor", - "tokio-io", - "tokio-threadpool", - "tokio-timer", - "url 1.7.2", - "uuid 0.7.4", - "winreg", + "proc-macro2", + "quote", + "syn", ] [[package]] -name = "retry" -version = "1.2.1" +name = "serde_json" +version = "1.0.145" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d0ee4a654b43dd7e3768be7a1c0fc20e90f0a84b72a60ffb6c11e1cae2545c2e" +checksum = "402a6f66d8c709116cf22f558eab210f5a50187f702eb4d7e5ef38d9a7f1c79c" dependencies = [ - "rand 0.7.3", + "itoa", + "memchr", + "ryu", + "serde", + "serde_core", ] [[package]] -name = "ring" -version = "0.16.20" +name = "serde_repr" +version = "0.1.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3053cf52e236a3ed746dfc745aa9cacf1b791d846bdaf412f60a8d7d6e17c8fc" +checksum = "175ee3e80ae9982737ca543e96133087cbd9a485eecc3bc4de9c1a37b47ea59c" dependencies = [ - "cc", - "libc", - "once_cell", - "spin", - "untrusted", - "web-sys", - "winapi 0.3.9", + "proc-macro2", + "quote", + "syn", ] [[package]] -name = "rustc-demangle" -version = "0.1.19" +name = "serde_urlencoded" +version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "410f7acf3cb3a44527c5d9546bad4bf4e6c460915d5f9f2fc524498bfe8f70ce" +checksum = "d3491c14715ca2294c4d6a88f15e84739788c1d030eed8c110436aafdaa2f3fd" +dependencies = [ + "form_urlencoded", + "itoa", + "ryu", + "serde", +] [[package]] -name = "rustc_version" -version = "0.2.3" +name = "serde_with" +version = "3.15.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a" +checksum = "aa66c845eee442168b2c8134fec70ac50dc20e760769c8ba0ad1319ca1959b04" dependencies = [ - "semver 0.9.0", + "base64 0.22.1", + "chrono", + "hex", + "indexmap 1.9.3", + "indexmap 2.12.0", + "schemars 0.9.0", + "schemars 1.0.4", + "serde_core", + "serde_json", + "time", ] [[package]] -name = "rustls" -version = "0.17.0" +name = "serde_yaml" +version = "0.9.34+deprecated" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0d4a31f5d68413404705d6982529b0e11a9aacd4839d1d6222ee3b8cb4015e1" +checksum = "6a8b1a1a2ebf674015cc02edccce75287f1a0130d394307b36743c2f5d504b47" dependencies = [ - "base64 0.11.0", - "log", - "ring", - "sct", - "webpki", + "indexmap 2.12.0", + "itoa", + "ryu", + "serde", + "unsafe-libyaml", ] [[package]] -name = "rustls-native-certs" -version = "0.3.0" +name = "sha2" +version = "0.10.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a75ffeb84a6bd9d014713119542ce415db3a3e4748f0bfce1e1416cd224a23a5" +checksum = "a7507d819769d01a365ab707794a4084392c824f54a7a6a7862f8c3d0892b283" dependencies = [ - "openssl-probe", - "rustls", - "schannel", - "security-framework 0.4.4", + "cfg-if", + "cpufeatures", + "digest", ] [[package]] -name = "ryu" -version = "1.0.5" +name = "shlex" +version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "71d301d4193d031abdd79ff7e3dd721168a9572ef3fe51a1517aba235bd8f86e" +checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" [[package]] -name = "schannel" -version = "0.1.19" +name = "siphasher" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f05ba609c234e60bee0d547fe94a4c7e9da733d1c962cf6e59efa4cd9c8bc75" -dependencies = [ - "lazy_static", - "winapi 0.3.9", -] +checksum = "56199f7ddabf13fe5074ce809e7d3f42b42ae711800501b5b16ea82ad029c39d" [[package]] -name = "scopeguard" -version = "1.1.0" +name = "slab" +version = "0.4.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" +checksum = "7a2ae44ef20feb57a68b23d846850f861394c2e02dc425a50098ae8c90267589" [[package]] -name = "sct" -version = "0.6.1" +name = "smallvec" +version = "1.15.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b362b83898e0e69f38515b82ee15aa80636befe47c3b6d3d89a911e78fc228ce" -dependencies = [ - "ring", - "untrusted", -] +checksum = "67b1b7a3b5fe4f1376887184045fcf45c69e92af734b7aaddc05fb777b6fbd03" [[package]] -name = "security-framework" -version = "0.4.4" +name = "socket2" +version = "0.5.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "64808902d7d99f78eaddd2b4e2509713babc3dc3c85ad6f4c447680f3c01e535" +checksum = "e22376abed350d73dd1cd119b57ffccad95b4e585a7cda43e286245ce23c0678" dependencies = [ - "bitflags", - "core-foundation 0.7.0", - "core-foundation-sys 0.7.0", "libc", - "security-framework-sys 0.4.3", + "windows-sys 0.52.0", ] [[package]] -name = "security-framework" -version = "2.2.0" +name = "socket2" +version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3670b1d2fdf6084d192bc71ead7aabe6c06aa2ea3fbd9cc3ac111fa5c2b1bd84" +checksum = "17129e116933cf371d018bb80ae557e889637989d8638274fb25622827b03881" dependencies = [ - "bitflags", - "core-foundation 0.9.1", - "core-foundation-sys 0.8.2", "libc", - "security-framework-sys 2.2.0", + "windows-sys 0.60.2", ] [[package]] -name = "security-framework-sys" -version = "0.4.3" +name = "stable_deref_trait" +version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "17bf11d99252f512695eb468de5516e5cf75455521e69dfe343f3b74e4748405" +checksum = "6ce2be8dc25455e1f91df71bfa12ad37d7af1092ae736f3a6cd0e37bc7810596" + +[[package]] +name = "strsim" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" + +[[package]] +name = "syn" +version = "2.0.108" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da58917d35242480a05c2897064da0a80589a2a0476c9a3f2fdc83b53502e917" dependencies = [ - "core-foundation-sys 0.7.0", - "libc", + "proc-macro2", + "quote", + "unicode-ident", ] [[package]] -name = "security-framework-sys" -version = "2.2.0" +name = "sync_wrapper" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2047c6ded9c721764247e62cd3b03c09ffc529b2ba5b10ec482ae507a4a70160" + +[[package]] +name = "synstructure" +version = "0.13.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3676258fd3cfe2c9a0ec99ce3038798d847ce3e4bb17746373eb9f0f1ac16339" +checksum = "728a70f3dbaf5bab7f0c4b1ac8d7ae5ea60a4b5549c8a5914361c99147a709d2" dependencies = [ - "core-foundation-sys 0.8.2", - "libc", + "proc-macro2", + "quote", + "syn", ] [[package]] -name = "semver" -version = "0.9.0" +name = "system-configuration" +version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403" +checksum = "ba3a3adc5c275d719af8cb4272ea1c4a6d668a777f37e115f6d11ddbc1c8e0e7" dependencies = [ - "semver-parser", + "bitflags 1.3.2", + "core-foundation", + "system-configuration-sys", ] [[package]] -name = "semver" -version = "0.10.0" +name = "system-configuration-sys" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "394cec28fa623e00903caf7ba4fa6fb9a0e260280bb8cdbbba029611108a0190" +checksum = "a75fb188eb626b924683e3b95e3a48e63551fcfb51949de2f06a9d91dbee93c9" dependencies = [ - "semver-parser", + "core-foundation-sys", + "libc", ] [[package]] -name = "semver-parser" -version = "0.7.0" +name = "tempfile" +version = "3.23.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" +checksum = "2d31c77bdf42a745371d260a26ca7163f1e0924b64afa0b688e61b5a9fa02f16" +dependencies = [ + "fastrand", + "getrandom 0.3.4", + "once_cell", + "rustix", + "windows-sys 0.61.2", +] [[package]] -name = "serde" -version = "1.0.125" +name = "thiserror" +version = "2.0.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "558dc50e1a5a5fa7112ca2ce4effcb321b0300c0d4ccf0776a9f60cd89031171" +checksum = "f63587ca0f12b72a0600bcba1d40081f830876000bb46dd2337a3051618f4fc8" dependencies = [ - "serde_derive", + "thiserror-impl", ] [[package]] -name = "serde_derive" -version = "1.0.125" +name = "thiserror-impl" +version = "2.0.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b093b7a2bb58203b5da3056c05b4ec1fed827dcfdb37347a8841695263b3d06d" +checksum = "3ff15c8ecd7de3849db632e14d18d2571fa09dfc5ed93479bc4485c7a517c913" dependencies = [ "proc-macro2", "quote", @@ -2202,793 +2201,785 @@ dependencies = [ ] [[package]] -name = "serde_json" -version = "1.0.64" +name = "time" +version = "0.3.44" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "799e97dc9fdae36a5c8b8f2cae9ce2ee9fdce2058c57a93e6099d919fd982f79" +checksum = "91e7d9e3bb61134e77bde20dd4825b97c010155709965fedf0f49bb138e52a9d" dependencies = [ + "deranged", "itoa", - "ryu", + "num-conv", + "powerfmt", "serde", + "time-core", + "time-macros", ] [[package]] -name = "serde_urlencoded" -version = "0.5.5" +name = "time-core" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "40868e7c1d2f0b8d73e4a8c7f0ff63af4f6d19be117e90bd73eb1d62cf831c6b" + +[[package]] +name = "time-macros" +version = "0.2.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "642dd69105886af2efd227f75a520ec9b44a820d65bc133a9131f7d229fd165a" +checksum = "30cfb0125f12d9c277f35663a0a33f8c30190f4e4574868a330595412d34ebf3" dependencies = [ - "dtoa", - "itoa", - "serde", - "url 1.7.2", + "num-conv", + "time-core", ] [[package]] -name = "serde_yaml" -version = "0.8.17" +name = "tinystr" +version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "15654ed4ab61726bf918a39cb8d98a2e2995b002387807fa6ba58fdf7f59bb23" +checksum = "42d3e9c45c09de15d06dd8acf5f4e0e399e85927b7f00711024eb7ae10fa4869" dependencies = [ - "dtoa", - "linked-hash-map", - "serde", - "yaml-rust 0.4.5", + "displaydoc", + "zerovec", ] [[package]] -name = "sha-1" -version = "0.8.2" +name = "tokio" +version = "1.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f7d94d0bede923b3cea61f3f1ff57ff8cdfd77b400fb8f9998949e0cf04163df" +checksum = "ff360e02eab121e0bc37a2d3b4d4dc622e6eda3a8e5253d5435ecf5bd4c68408" dependencies = [ - "block-buffer", - "digest", - "fake-simd", - "opaque-debug", + "bytes", + "libc", + "mio", + "pin-project-lite", + "socket2 0.6.1", + "tokio-macros", + "windows-sys 0.61.2", ] [[package]] -name = "shlex" -version = "0.1.1" +name = "tokio-macros" +version = "2.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7fdf1b9db47230893d76faad238fd6097fd6d6a9245cd7a4d90dbd639536bbd2" +checksum = "af407857209536a95c8e56f8231ef2c2e2aff839b22e07a1ffcbc617e9db9fa5" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] [[package]] -name = "siphasher" -version = "0.3.5" +name = "tokio-native-tls" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cbce6d4507c7e4a3962091436e56e95290cb71fa302d0d270e32130b75fbff27" +checksum = "bbae76ab933c85776efabc971569dd6119c580d8f5d448769dec1764bf796ef2" +dependencies = [ + "native-tls", + "tokio", +] [[package]] -name = "slab" -version = "0.4.3" +name = "tokio-util" +version = "0.7.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f173ac3d1a7e3b28003f40de0b5ce7fe2710f9b9dc3fc38664cebee46b3b6527" +checksum = "14307c986784f72ef81c89db7d9e28d6ac26d16213b109ea501696195e6e3ce5" +dependencies = [ + "bytes", + "futures-core", + "futures-sink", + "pin-project-lite", + "tokio", +] [[package]] -name = "smallvec" -version = "0.6.14" +name = "tower-service" +version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b97fcaeba89edba30f044a10c6a3cc39df9c3f17d7cd829dd1446cab35f890e0" +checksum = "8df9b6e13f2d32c91b9bd719c00d1958837bc7dec474d94952798cc8e69eeec3" + +[[package]] +name = "tracing" +version = "0.1.41" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "784e0ac535deb450455cbfa28a6f0df145ea1bb7ae51b821cf5e7927fdcfbdd0" dependencies = [ - "maybe-uninit", + "pin-project-lite", + "tracing-core", ] [[package]] -name = "socket2" -version = "0.3.19" +name = "tracing-core" +version = "0.1.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "122e570113d28d773067fab24266b66753f6ea915758651696b6e35e49f88d6e" +checksum = "b9d12581f227e93f094d3af2ae690a574abb8a2b9b7a96e7cfe9647b2b617678" dependencies = [ - "cfg-if 1.0.0", - "libc", - "winapi 0.3.9", + "once_cell", ] [[package]] -name = "spin" -version = "0.5.2" +name = "try-lock" +version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d" +checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b" [[package]] -name = "string" -version = "0.2.1" +name = "typenum" +version = "1.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d24114bfcceb867ca7f71a0d3fe45d45619ec47a6fbfa98cb14e14250bfa5d6d" -dependencies = [ - "bytes 0.4.12", -] +checksum = "562d481066bde0658276a35467c4af00bdc6ee726305698a55b86e61d7ad82bb" [[package]] -name = "strsim" -version = "0.8.0" +name = "ucd-trie" +version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a" +checksum = "2896d95c02a80c6d6a5d6e953d479f5ddf2dfdb6a244441010e373ac0fb88971" [[package]] -name = "syn" -version = "1.0.72" +name = "unicode-ident" +version = "1.0.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1e8cdbefb79a9a5a65e0db8b47b723ee907b7c7f8496c76a1770b5c310bab82" -dependencies = [ - "proc-macro2", - "quote", - "unicode-xid", -] +checksum = "462eeb75aeb73aea900253ce739c8e18a67423fadf006037cd3ff27e82748a06" [[package]] -name = "synstructure" -version = "0.12.4" +name = "unsafe-libyaml" +version = "0.2.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b834f2d66f734cb897113e34aaff2f1ab4719ca946f9a7358dba8f8064148701" -dependencies = [ - "proc-macro2", - "quote", - "syn", - "unicode-xid", -] +checksum = "673aac59facbab8a9007c7f6108d11f63b603f7cabff99fabf650fea5c32b861" [[package]] -name = "tempfile" -version = "3.2.0" +name = "uritemplate-next" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dac1c663cfc93810f88aed9b8941d48cabf856a1b111c29a40439018d870eb22" +checksum = "bcde98d1fc3f528255b1ecb22fb688ee0d23deb672a8c57127df10b98b4bd18c" dependencies = [ - "cfg-if 1.0.0", - "libc", - "rand 0.8.3", - "redox_syscall 0.2.8", - "remove_dir_all", - "winapi 0.3.9", + "regex", ] [[package]] -name = "termcolor" -version = "1.1.2" +name = "url" +version = "2.5.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2dfed899f0eb03f32ee8c6a0aabdb8a7949659e3466561fc0adf54e26d88c5f4" +checksum = "08bc136a29a3d1758e07a9cca267be308aeebf5cfd5a10f3f67ab2097683ef5b" dependencies = [ - "winapi-util", + "form_urlencoded", + "idna", + "percent-encoding", + "serde", ] [[package]] -name = "textwrap" -version = "0.11.0" +name = "utf8_iter" +version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060" -dependencies = [ - "unicode-width", -] +checksum = "b6c140620e7ffbb22c2dee59cafe6084a59b5ffc27a8859a5f0d494b5d52b6be" [[package]] -name = "thiserror" -version = "1.0.24" +name = "utf8parse" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" + +[[package]] +name = "uuid" +version = "1.18.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e0f4a65597094d4483ddaed134f409b2cb7c1beccf25201a9f73c719254fa98e" +checksum = "2f87b8aa10b915a06587d0dec516c282ff295b475d94abf425d62b57710070a2" dependencies = [ - "thiserror-impl", + "getrandom 0.3.4", + "js-sys", + "wasm-bindgen", ] [[package]] -name = "thiserror-impl" -version = "1.0.24" +name = "valico" +version = "4.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7765189610d8241a44529806d6fd1f2e0a08734313a35d5b3a556f92b381f3c0" +checksum = "ca8a0a4df97f827fcbcbe69c65364acddddf3a4bb50e6507f63361177a7ea7a4" dependencies = [ - "proc-macro2", - "quote", - "syn", + "addr", + "base64 0.21.7", + "chrono", + "downcast-rs", + "erased-serde", + "fancy-regex", + "json-pointer", + "jsonway", + "percent-encoding", + "phf", + "phf_codegen", + "serde", + "serde_json", + "uritemplate-next", + "url", + "uuid", ] [[package]] -name = "time" -version = "0.1.43" +name = "vcpkg" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" + +[[package]] +name = "version_check" +version = "0.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" + +[[package]] +name = "void" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d" + +[[package]] +name = "walkdir" +version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca8a50ef2360fbd1eeb0ecd46795a87a19024eb4b53c5dc916ca1fd95fe62438" +checksum = "29790946404f91d9c5d06f9874efddea1dc06c5efe94541a7d6863108e3a5e4b" dependencies = [ - "libc", - "winapi 0.3.9", + "same-file", + "winapi-util", ] [[package]] -name = "tinyvec" -version = "1.2.0" +name = "want" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b5220f05bb7de7f3f53c7c065e1199b3172696fe2db9f9c4d8ad9b4ee74c342" +checksum = "bfa7760aed19e106de2c7c0b581b509f2f25d3dacaf737cb82ac61bc6d760b0e" dependencies = [ - "tinyvec_macros", + "try-lock", ] [[package]] -name = "tinyvec_macros" -version = "0.1.0" +name = "wasi" +version = "0.11.1+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cda74da7e1a664f795bb1f8a87ec406fb89a02522cf6e50620d016add6dbbf5c" +checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b" [[package]] -name = "tokio" -version = "0.1.22" +name = "wasip2" +version = "1.0.1+wasi-0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a09c0b5bb588872ab2f09afa13ee6e9dac11e10a0ec9e8e3ba39a5a5d530af6" +checksum = "0562428422c63773dad2c345a1882263bbf4d65cf3f42e90921f787ef5ad58e7" dependencies = [ - "bytes 0.4.12", - "futures 0.1.31", - "mio", - "num_cpus", - "tokio-current-thread", - "tokio-executor", - "tokio-io", - "tokio-reactor", - "tokio-tcp", - "tokio-threadpool", - "tokio-timer", + "wit-bindgen", ] [[package]] -name = "tokio" -version = "0.2.25" +name = "wasm-bindgen" +version = "0.2.105" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6703a273949a90131b290be1fe7b039d0fc884aa1935860dfcbe056f28cd8092" +checksum = "da95793dfc411fbbd93f5be7715b0578ec61fe87cb1a42b12eb625caa5c5ea60" dependencies = [ - "bytes 0.5.6", - "fnv", - "futures-core", - "iovec", - "lazy_static", - "libc", - "memchr", - "mio", - "mio-uds", - "pin-project-lite 0.1.12", - "slab", + "cfg-if", + "once_cell", + "rustversion", + "wasm-bindgen-macro", + "wasm-bindgen-shared", ] [[package]] -name = "tokio-buf" -version = "0.1.1" +name = "wasm-bindgen-futures" +version = "0.4.55" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8fb220f46c53859a4b7ec083e41dec9778ff0b1851c0942b211edb89e0ccdc46" +checksum = "551f88106c6d5e7ccc7cd9a16f312dd3b5d36ea8b4954304657d5dfba115d4a0" dependencies = [ - "bytes 0.4.12", - "either", - "futures 0.1.31", + "cfg-if", + "js-sys", + "once_cell", + "wasm-bindgen", + "web-sys", ] [[package]] -name = "tokio-current-thread" -version = "0.1.7" +name = "wasm-bindgen-macro" +version = "0.2.105" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1de0e32a83f131e002238d7ccde18211c0a5397f60cbfffcb112868c2e0e20e" +checksum = "04264334509e04a7bf8690f2384ef5265f05143a4bff3889ab7a3269adab59c2" dependencies = [ - "futures 0.1.31", - "tokio-executor", + "quote", + "wasm-bindgen-macro-support", ] [[package]] -name = "tokio-executor" -version = "0.1.10" +name = "wasm-bindgen-macro-support" +version = "0.2.105" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fb2d1b8f4548dbf5e1f7818512e9c406860678f29c300cdf0ebac72d1a3a1671" +checksum = "420bc339d9f322e562942d52e115d57e950d12d88983a14c79b86859ee6c7ebc" dependencies = [ - "crossbeam-utils 0.7.2", - "futures 0.1.31", + "bumpalo", + "proc-macro2", + "quote", + "syn", + "wasm-bindgen-shared", ] [[package]] -name = "tokio-io" -version = "0.1.13" +name = "wasm-bindgen-shared" +version = "0.2.105" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "57fc868aae093479e3131e3d165c93b1c7474109d13c90ec0dda2a1bbfff0674" +checksum = "76f218a38c84bcb33c25ec7059b07847d465ce0e0a76b995e134a45adcb6af76" dependencies = [ - "bytes 0.4.12", - "futures 0.1.31", - "log", + "unicode-ident", ] [[package]] -name = "tokio-reactor" -version = "0.1.12" +name = "web-sys" +version = "0.3.82" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09bc590ec4ba8ba87652da2068d150dcada2cfa2e07faae270a5e0409aa51351" +checksum = "3a1f95c0d03a47f4ae1f7a64643a6bb97465d9b740f0fa8f90ea33915c99a9a1" dependencies = [ - "crossbeam-utils 0.7.2", - "futures 0.1.31", - "lazy_static", - "log", - "mio", - "num_cpus", - "parking_lot", - "slab", - "tokio-executor", - "tokio-io", - "tokio-sync", + "js-sys", + "wasm-bindgen", ] [[package]] -name = "tokio-rustls" -version = "0.13.1" +name = "winapi" +version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "15cb62a0d2770787abc96e99c1cd98fcf17f94959f3af63ca85bdfb203f051b4" +checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" dependencies = [ - "futures-core", - "rustls", - "tokio 0.2.25", - "webpki", + "winapi-i686-pc-windows-gnu", + "winapi-x86_64-pc-windows-gnu", ] [[package]] -name = "tokio-sync" -version = "0.1.8" +name = "winapi-i686-pc-windows-gnu" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "edfe50152bc8164fcc456dab7891fa9bf8beaf01c5ee7e1dd43a397c3cf87dee" -dependencies = [ - "fnv", - "futures 0.1.31", -] +checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" [[package]] -name = "tokio-tcp" -version = "0.1.4" +name = "winapi-util" +version = "0.1.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "98df18ed66e3b72e742f185882a9e201892407957e45fbff8da17ae7a7c51f72" +checksum = "c2a7b1c03c876122aa43f3020e6c3c3ee5c05081c9a00739faf7503aeba10d22" dependencies = [ - "bytes 0.4.12", - "futures 0.1.31", - "iovec", - "mio", - "tokio-io", - "tokio-reactor", + "windows-sys 0.61.2", ] [[package]] -name = "tokio-threadpool" -version = "0.1.18" +name = "winapi-x86_64-pc-windows-gnu" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "df720b6581784c118f0eb4310796b12b1d242a7eb95f716a8367855325c25f89" +checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" + +[[package]] +name = "windows-core" +version = "0.62.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8e83a14d34d0623b51dce9581199302a221863196a1dde71a7663a4c2be9deb" dependencies = [ - "crossbeam-deque 0.7.3", - "crossbeam-queue", - "crossbeam-utils 0.7.2", - "futures 0.1.31", - "lazy_static", - "log", - "num_cpus", - "slab", - "tokio-executor", + "windows-implement", + "windows-interface", + "windows-link", + "windows-result", + "windows-strings", ] [[package]] -name = "tokio-timer" -version = "0.2.13" +name = "windows-implement" +version = "0.60.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "93044f2d313c95ff1cb7809ce9a7a05735b012288a888b62d4434fd58c94f296" +checksum = "053e2e040ab57b9dc951b72c264860db7eb3b0200ba345b4e4c3b14f67855ddf" dependencies = [ - "crossbeam-utils 0.7.2", - "futures 0.1.31", - "slab", - "tokio-executor", + "proc-macro2", + "quote", + "syn", ] [[package]] -name = "tokio-util" -version = "0.3.1" +name = "windows-interface" +version = "0.59.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be8242891f2b6cbef26a2d7e8605133c2c554cd35b3e4948ea892d6d68436499" +checksum = "3f316c4a2570ba26bbec722032c4099d8c8bc095efccdc15688708623367e358" dependencies = [ - "bytes 0.5.6", - "futures-core", - "futures-sink", - "log", - "pin-project-lite 0.1.12", - "tokio 0.2.25", + "proc-macro2", + "quote", + "syn", ] [[package]] -name = "tower-service" -version = "0.3.1" +name = "windows-link" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "360dfd1d6d30e05fda32ace2c8c70e9c0a9da713275777f5a4dbb8a1893930c6" +checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5" [[package]] -name = "tracing" -version = "0.1.26" +name = "windows-result" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09adeb8c97449311ccd28a427f96fb563e7fd31aabf994189879d9da2394b89d" +checksum = "7781fa89eaf60850ac3d2da7af8e5242a5ea78d1a11c49bf2910bb5a73853eb5" dependencies = [ - "cfg-if 1.0.0", - "log", - "pin-project-lite 0.2.6", - "tracing-core", + "windows-link", ] [[package]] -name = "tracing-core" -version = "0.1.18" +name = "windows-strings" +version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a9ff14f98b1a4b289c6248a023c1c2fa1491062964e9fed67ab29c4e4da4a052" +checksum = "7837d08f69c77cf6b07689544538e017c1bfcf57e34b4c0ff58e6c2cd3b37091" dependencies = [ - "lazy_static", + "windows-link", ] [[package]] -name = "tracing-futures" -version = "0.2.5" +name = "windows-sys" +version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97d095ae15e245a057c8e8451bab9b3ee1e1f68e9ba2b4fbc18d0ac5237835f2" +checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" dependencies = [ - "pin-project 1.0.7", - "tracing", + "windows-targets 0.48.5", ] [[package]] -name = "try-lock" -version = "0.2.3" +name = "windows-sys" +version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "59547bce71d9c38b83d9c0e92b6066c4253371f15005def0c30d9657f50c7642" +checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" +dependencies = [ + "windows-targets 0.52.6", +] [[package]] -name = "try_from" -version = "0.3.2" +name = "windows-sys" +version = "0.59.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "283d3b89e1368717881a9d51dad843cc435380d8109c9e47d38780a324698d8b" +checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" dependencies = [ - "cfg-if 0.1.10", + "windows-targets 0.52.6", ] [[package]] -name = "typenum" -version = "1.13.0" +name = "windows-sys" +version = "0.60.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "879f6906492a7cd215bfa4cf595b600146ccfac0c79bcbd1f3000162af5e8b06" +checksum = "f2f500e4d28234f72040990ec9d39e3a6b950f9f22d3dba18416c35882612bcb" +dependencies = [ + "windows-targets 0.53.5", +] [[package]] -name = "ucd-trie" -version = "0.1.3" +name = "windows-sys" +version = "0.61.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "56dee185309b50d1f11bfedef0fe6d036842e3fb77413abef29f8f8d1c5d4c1c" +checksum = "ae137229bcbd6cdf0f7b80a31df61766145077ddf49416a728b02cb3921ff3fc" +dependencies = [ + "windows-link", +] [[package]] -name = "unicase" -version = "2.6.0" +name = "windows-targets" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "50f37be617794602aabbeee0be4f259dc1778fabe05e2d67ee8f79326d5cb4f6" +checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c" dependencies = [ - "version_check", + "windows_aarch64_gnullvm 0.48.5", + "windows_aarch64_msvc 0.48.5", + "windows_i686_gnu 0.48.5", + "windows_i686_msvc 0.48.5", + "windows_x86_64_gnu 0.48.5", + "windows_x86_64_gnullvm 0.48.5", + "windows_x86_64_msvc 0.48.5", ] [[package]] -name = "unicode-bidi" -version = "0.3.5" +name = "windows-targets" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eeb8be209bb1c96b7c177c7420d26e04eccacb0eeae6b980e35fcb74678107e0" +checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" dependencies = [ - "matches", + "windows_aarch64_gnullvm 0.52.6", + "windows_aarch64_msvc 0.52.6", + "windows_i686_gnu 0.52.6", + "windows_i686_gnullvm 0.52.6", + "windows_i686_msvc 0.52.6", + "windows_x86_64_gnu 0.52.6", + "windows_x86_64_gnullvm 0.52.6", + "windows_x86_64_msvc 0.52.6", ] [[package]] -name = "unicode-normalization" -version = "0.1.17" +name = "windows-targets" +version = "0.53.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07fbfce1c8a97d547e8b5334978438d9d6ec8c20e38f56d4a4374d181493eaef" +checksum = "4945f9f551b88e0d65f3db0bc25c33b8acea4d9e41163edf90dcd0b19f9069f3" dependencies = [ - "tinyvec", + "windows-link", + "windows_aarch64_gnullvm 0.53.1", + "windows_aarch64_msvc 0.53.1", + "windows_i686_gnu 0.53.1", + "windows_i686_gnullvm 0.53.1", + "windows_i686_msvc 0.53.1", + "windows_x86_64_gnu 0.53.1", + "windows_x86_64_gnullvm 0.53.1", + "windows_x86_64_msvc 0.53.1", ] [[package]] -name = "unicode-width" -version = "0.1.8" +name = "windows_aarch64_gnullvm" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9337591893a19b88d8d87f2cec1e73fad5cdfd10e5a6f349f498ad6ea2ffb1e3" +checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" [[package]] -name = "unicode-xid" -version = "0.2.2" +name = "windows_aarch64_gnullvm" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ccb82d61f80a663efe1f787a51b16b5a51e3314d6ac365b08639f52387b33f3" +checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" [[package]] -name = "untrusted" -version = "0.7.1" +name = "windows_aarch64_gnullvm" +version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a156c684c91ea7d62626509bce3cb4e1d9ed5c4d978f7b4352658f96a4c26b4a" +checksum = "a9d8416fa8b42f5c947f8482c43e7d89e73a173cead56d044f6a56104a6d1b53" [[package]] -name = "uritemplate-next" -version = "0.2.0" +name = "windows_aarch64_msvc" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bcde98d1fc3f528255b1ecb22fb688ee0d23deb672a8c57127df10b98b4bd18c" -dependencies = [ - "regex", -] +checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" [[package]] -name = "url" -version = "1.7.2" +name = "windows_aarch64_msvc" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd4e7c0d531266369519a4aa4f399d748bd37043b00bde1e4ff1f60a120b355a" -dependencies = [ - "idna 0.1.5", - "matches", - "percent-encoding 1.0.1", -] +checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" [[package]] -name = "url" -version = "2.2.2" +name = "windows_aarch64_msvc" +version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a507c383b2d33b5fc35d1861e77e6b383d158b2da5e14fe51b83dfedf6fd578c" -dependencies = [ - "form_urlencoded", - "idna 0.2.3", - "matches", - "percent-encoding 2.1.0", -] +checksum = "b9d782e804c2f632e395708e99a94275910eb9100b2114651e04744e9b125006" [[package]] -name = "uuid" -version = "0.7.4" +name = "windows_i686_gnu" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "90dbc611eb48397705a6b0f6e917da23ae517e4d127123d2cf7674206627d32a" -dependencies = [ - "rand 0.6.5", -] +checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" [[package]] -name = "uuid" -version = "0.8.2" +name = "windows_i686_gnu" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bc5cf98d8186244414c848017f0e2676b3fcb46807f6668a97dfe67359a3c4b7" -dependencies = [ - "getrandom 0.2.2", -] +checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" [[package]] -name = "valico" -version = "3.6.0" +name = "windows_i686_gnu" +version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d81a70f930f9e6cd04669d38abcf232f96b193acceb0f4c006427ddec6e08b10" -dependencies = [ - "base64 0.13.0", - "chrono", - "json-pointer", - "jsonway", - "percent-encoding 2.1.0", - "phf", - "phf_codegen", - "publicsuffix", - "regex", - "serde", - "serde_json", - "uritemplate-next", - "url 2.2.2", - "uuid 0.8.2", -] +checksum = "960e6da069d81e09becb0ca57a65220ddff016ff2d6af6a223cf372a506593a3" [[package]] -name = "vcpkg" -version = "0.2.12" +name = "windows_i686_gnullvm" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cbdbff6266a24120518560b5dc983096efb98462e51d0d68169895b237be3e5d" +checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" [[package]] -name = "vec_map" -version = "0.8.2" +name = "windows_i686_gnullvm" +version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1bddf1187be692e79c5ffeab891132dfb0f236ed36a43c7ed39f1165ee20191" +checksum = "fa7359d10048f68ab8b09fa71c3daccfb0e9b559aed648a8f95469c27057180c" [[package]] -name = "version_check" -version = "0.9.3" +name = "windows_i686_msvc" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5fecdca9a5291cc2b8dcf7dc02453fee791a280f3743cb0905f8822ae463b3fe" +checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" [[package]] -name = "void" -version = "1.0.2" +name = "windows_i686_msvc" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d" +checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" [[package]] -name = "walkdir" -version = "0.1.8" +name = "windows_i686_msvc" +version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c66c0b9792f0a765345452775f3adbd28dde9d33f30d13e5dcc5ae17cf6f3780" -dependencies = [ - "kernel32-sys", - "winapi 0.2.8", -] +checksum = "1e7ac75179f18232fe9c285163565a57ef8d3c89254a30685b57d83a38d326c2" [[package]] -name = "want" -version = "0.2.0" +name = "windows_x86_64_gnu" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6395efa4784b027708f7451087e647ec73cc74f5d9bc2e418404248d679a230" -dependencies = [ - "futures 0.1.31", - "log", - "try-lock", -] +checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" [[package]] -name = "want" -version = "0.3.0" +name = "windows_x86_64_gnu" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ce8a968cb1cd110d136ff8b819a556d6fb6d919363c61534f6860c7eb172ba0" -dependencies = [ - "log", - "try-lock", -] +checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" [[package]] -name = "wasi" -version = "0.9.0+wasi-snapshot-preview1" +name = "windows_x86_64_gnu" +version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cccddf32554fecc6acb585f82a32a72e28b48f8c4c1883ddfeeeaa96f7d8e519" +checksum = "9c3842cdd74a865a8066ab39c8a7a473c0778a3f29370b5fd6b4b9aa7df4a499" [[package]] -name = "wasi" -version = "0.10.2+wasi-snapshot-preview1" +name = "windows_x86_64_gnullvm" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fd6fbd9a79829dd1ad0cc20627bf1ed606756a7f77edff7b66b7064f9cb327c6" +checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" [[package]] -name = "wasm-bindgen" -version = "0.2.74" +name = "windows_x86_64_gnullvm" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d54ee1d4ed486f78874278e63e4069fc1ab9f6a18ca492076ffb90c5eb2997fd" -dependencies = [ - "cfg-if 1.0.0", - "wasm-bindgen-macro", -] +checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" [[package]] -name = "wasm-bindgen-backend" -version = "0.2.74" +name = "windows_x86_64_gnullvm" +version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b33f6a0694ccfea53d94db8b2ed1c3a8a4c86dd936b13b9f0a15ec4a451b900" -dependencies = [ - "bumpalo", - "lazy_static", - "log", - "proc-macro2", - "quote", - "syn", - "wasm-bindgen-shared", -] +checksum = "0ffa179e2d07eee8ad8f57493436566c7cc30ac536a3379fdf008f47f6bb7ae1" [[package]] -name = "wasm-bindgen-macro" -version = "0.2.74" +name = "windows_x86_64_msvc" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "088169ca61430fe1e58b8096c24975251700e7b1f6fd91cc9d59b04fb9b18bd4" -dependencies = [ - "quote", - "wasm-bindgen-macro-support", -] +checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" [[package]] -name = "wasm-bindgen-macro-support" -version = "0.2.74" +name = "windows_x86_64_msvc" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be2241542ff3d9f241f5e2cb6dd09b37efe786df8851c54957683a49f0987a97" -dependencies = [ - "proc-macro2", - "quote", - "syn", - "wasm-bindgen-backend", - "wasm-bindgen-shared", -] +checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" [[package]] -name = "wasm-bindgen-shared" -version = "0.2.74" +name = "windows_x86_64_msvc" +version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d7cff876b8f18eed75a66cf49b65e7f967cb354a7aa16003fb55dbfd25b44b4f" +checksum = "d6bbff5f0aada427a1e5a6da5f1f98158182f26556f345ac9e04d36d0ebed650" [[package]] -name = "web-sys" -version = "0.3.51" +name = "winreg" +version = "0.50.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e828417b379f3df7111d3a2a9e5753706cae29c41f7c4029ee9fd77f3e09e582" +checksum = "524e57b2c537c0f9b1e69f1965311ec12182b4122e45035b1508cd24d2adadb1" dependencies = [ - "js-sys", - "wasm-bindgen", + "cfg-if", + "windows-sys 0.48.0", ] [[package]] -name = "webpki" -version = "0.21.4" +name = "wit-bindgen" +version = "0.46.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b8e38c0608262c46d4a56202ebabdeb094cef7e560ca7a226c6bf055188aa4ea" -dependencies = [ - "ring", - "untrusted", -] +checksum = "f17a85883d4e6d00e8a97c586de764dabcc06133f7f1d55dce5cdc070ad7fe59" [[package]] -name = "webpki-roots" -version = "0.19.0" +name = "writeable" +version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f8eff4b7516a57307f9349c64bf34caa34b940b66fed4b2fb3136cb7386e5739" -dependencies = [ - "webpki", -] +checksum = "9edde0db4769d2dc68579893f2306b26c6ecfbe0ef499b013d731b7b9247e0b9" [[package]] -name = "winapi" -version = "0.2.8" +name = "yaml-rust2" +version = "0.10.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "167dc9d6949a9b857f3451275e911c3f44255842c1f7a76f33c55103a909087a" +checksum = "2462ea039c445496d8793d052e13787f2b90e750b833afee748e601c17621ed9" +dependencies = [ + "arraydeque", + "encoding_rs", + "hashlink", +] [[package]] -name = "winapi" -version = "0.3.9" +name = "yoke" +version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" +checksum = "72d6e5c6afb84d73944e5cedb052c4680d5657337201555f9f2a16b7406d4954" dependencies = [ - "winapi-i686-pc-windows-gnu", - "winapi-x86_64-pc-windows-gnu", + "stable_deref_trait", + "yoke-derive", + "zerofrom", ] [[package]] -name = "winapi-build" -version = "0.1.1" +name = "yoke-derive" +version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2d315eee3b34aca4797b2da6b13ed88266e6d612562a0c46390af8299fc699bc" +checksum = "b659052874eb698efe5b9e8cf382204678a0086ebf46982b79d6ca3182927e5d" +dependencies = [ + "proc-macro2", + "quote", + "syn", + "synstructure", +] [[package]] -name = "winapi-i686-pc-windows-gnu" -version = "0.4.0" +name = "zerocopy" +version = "0.8.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" +checksum = "0894878a5fa3edfd6da3f88c4805f4c8558e2b996227a3d864f47fe11e38282c" +dependencies = [ + "zerocopy-derive", +] [[package]] -name = "winapi-util" -version = "0.1.5" +name = "zerocopy-derive" +version = "0.8.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178" +checksum = "88d2b8d9c68ad2b9e4340d7832716a4d21a22a1154777ad56ea55c51a9cf3831" dependencies = [ - "winapi 0.3.9", + "proc-macro2", + "quote", + "syn", ] [[package]] -name = "winapi-x86_64-pc-windows-gnu" -version = "0.4.0" +name = "zerofrom" +version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" +checksum = "50cc42e0333e05660c3587f3bf9d0478688e15d870fab3346451ce7f8c9fbea5" +dependencies = [ + "zerofrom-derive", +] [[package]] -name = "winreg" -version = "0.6.2" +name = "zerofrom-derive" +version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b2986deb581c4fe11b621998a5e53361efe6b48a151178d0cd9eeffa4dc6acc9" +checksum = "d71e5d6e06ab090c67b5e44993ec16b72dcbaabc526db883a360057678b48502" dependencies = [ - "winapi 0.3.9", + "proc-macro2", + "quote", + "syn", + "synstructure", ] [[package]] -name = "ws2_32-sys" -version = "0.2.1" +name = "zerotrie" +version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d59cefebd0c892fa2dd6de581e937301d8552cb44489cdff035c6187cb63fa5e" +checksum = "2a59c17a5562d507e4b54960e8569ebee33bee890c70aa3fe7b97e85a9fd7851" dependencies = [ - "winapi 0.2.8", - "winapi-build", + "displaydoc", + "yoke", + "zerofrom", ] [[package]] -name = "yaml-rust" -version = "0.3.5" +name = "zerovec" +version = "0.11.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e66366e18dc58b46801afbf2ca7661a9f59cc8c5962c29892b6039b4f86fa992" +checksum = "6c28719294829477f525be0186d13efa9a3c602f7ec202ca9e353d310fb9a002" +dependencies = [ + "yoke", + "zerofrom", + "zerovec-derive", +] [[package]] -name = "yaml-rust" -version = "0.4.5" +name = "zerovec-derive" +version = "0.11.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "56c1936c4cc7a1c9ab21a1ebb602eb942ba868cbd44a99cb7cdc5892335e1c85" +checksum = "eadce39539ca5cb3985590102671f2567e659fca9666581ad3411d59207951f3" dependencies = [ - "linked-hash-map", + "proc-macro2", + "quote", + "syn", ] diff --git a/Cargo.toml b/Cargo.toml index e62156d2..32cdda8f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,9 +1,9 @@ [package] name = "cage" -version = "0.3.6" +version = "0.4.0" authors = ["Eric Kidd ", - "Derek Kastner "] -edition = "2018" + "Seamus Abshere "] +edition = "2021" description = "Develop multi-pod docker-compose apps" license = "MIT/Apache-2.0" @@ -26,33 +26,32 @@ cli_test_dir = "0.1.4" copy_dir = "0.1" [dependencies] -boondock = "0.1.0-alpha.1" -clap = { version = "2.14", features = ["yaml"] } -colored = "2.0" -compose_yml = "0.0.59" -dirs = "3.0.1" -env_logger = "0.7.1" -error-chain = "0.12.2" -failure = "0.1.7" +bollard = "0.19" +clap = { version = "4.5", features = ["derive", "string"] } +clap_complete = "4.5" +colored = "3.0" +faraday_compose_yml = { git = "https://github.com/faradayio/compose_yml" } +dirs = "6.0" +env_logger = "0.11" +anyhow = "1.0" +thiserror = "2.0" glob = "0.3" -handlebars = "3.0.1" -vault = { version = "1.0.0", package = "hashicorp_vault" } -include_dir = "0.6.0" -itertools = "0.9" +handlebars = "6.3" +vault = { version = "2.1", package = "hashicorp_vault" } +include_dir = "0.7" +itertools = "0.14" lazy_static = "1.0" log = "0.4.8" openssl-probe = "0.1" -rand = "0.7.3" +rand = "0.9" rayon = "1.3.0" regex = "1.3.6" -retry = "1.0.0" -semver = "0.10" +retry = "2.1" +semver = "1.0" serde = "1.0" serde_derive = "1.0" serde_json = "1.0" -serde_yaml = "0.8.11" -shlex = "0.1" -tokio = "0.2.17" +serde_yaml = "0.9" +shlex = "1.3" +tokio = { version = "1", features = ["rt", "macros"] } url = "2.1.1" -# Use an older version for compatibility with `clap`. -yaml-rust = "0.3" diff --git a/README.md b/README.md index 196ac7ab..c8fae86c 100644 --- a/README.md +++ b/README.md @@ -273,7 +273,7 @@ If you encounter an issue, it might help to set the following shell variables and re-run the command: ```sh -export RUST_BACKTRACE=1 RUST_LOG=cage=debug,compose_yml=debug +export RUST_BACKTRACE=1 RUST_LOG=cage=debug,faraday_compose_yml=debug ``` ## Development notes diff --git a/RELEASE_PROCESS.md b/RELEASE_PROCESS.md new file mode 100644 index 00000000..e4f52d38 --- /dev/null +++ b/RELEASE_PROCESS.md @@ -0,0 +1,154 @@ +# Release process + +This document describes how to create a new release of cage. + +## Prerequisites + +- You must have push access to the repository +- You must be able to push tags to GitHub + +## Steps to create a release + +### 1. Update the version in Cargo.toml + +Edit `Cargo.toml` and update the version number: + +```toml +[package] +name = "cage" +version = "0.5.0" # Update this line +``` + +### 2. Update CHANGELOG.md + +Add a new section for the version you're releasing. The format should be: + +```markdown +## 0.5.0 - YYYY-MM-DD + +### Added +- New features go here + +### Changed +- Changes to existing functionality + +### Fixed +- Bug fixes +``` + +Make sure to: +- Move items from the `## Unreleased` section to your new version section +- Use today's date in YYYY-MM-DD format +- Follow semantic versioning principles + +### 3. Commit the version changes + +```bash +git add Cargo.toml CHANGELOG.md +git commit -m "Bump version to 0.5.0" +git push origin master +``` + +### 4. Create and push a git tag + +The tag MUST match the version in Cargo.toml with a `v` prefix: + +```bash +# For version 0.5.0 in Cargo.toml, create tag v0.5.0 +git tag v0.5.0 +git push origin v0.5.0 +``` + +**CRITICAL**: The tag version (without the `v` prefix) must exactly match the version in `Cargo.toml`. If they don't match, the GitHub Actions workflow will fail. + +### 5. Wait for the automated build + +Once you push the tag, GitHub Actions will automatically: + +1. **Validate** that the tag version matches Cargo.toml +2. **Build** binaries for all platforms: + - Linux (x86_64, statically linked with musl) + - macOS Intel (x86_64) + - macOS Apple Silicon (aarch64) + - Windows (x86_64) +3. **Create** a GitHub release with all binaries attached +4. **Extract** the changelog section for this version and add it to the release notes + +You can monitor the progress at: https://github.com/faradayio/cage/actions + +The build typically takes 5-10 minutes. + +### 6. Verify the release + +Once the workflow completes: + +1. Go to https://github.com/faradayio/cage/releases +2. Verify the new release appears with the correct version +3. Check that all 4 binary archives are attached: + - `cage-v0.5.0-linux-x86_64.zip` + - `cage-v0.5.0-macos-x86_64.zip` + - `cage-v0.5.0-macos-aarch64.zip` + - `cage-v0.5.0-windows-x86_64.zip` +4. Verify the changelog appears in the release description +5. Optionally, download and test a binary to ensure it works + +## What if something goes wrong? + +### The workflow fails at validation + +**Error**: "Tag version (X.X.X) does not match Cargo.toml version (Y.Y.Y)" + +**Fix**: +1. Delete the tag locally: `git tag -d vX.X.X` +2. Delete the tag remotely: `git push origin :refs/tags/vX.X.X` +3. Fix the version in `Cargo.toml` to match your intended version +4. Commit and push the fix +5. Create the correct tag and push it again + +### The workflow fails during build + +**Fix**: +1. Check the Actions tab for the specific error +2. If it's a build error, fix the code issue +3. Delete the tag (see above) +4. Increment the version number (e.g., 0.5.0 → 0.5.1) +5. Update both `Cargo.toml` and `CHANGELOG.md` +6. Commit, push, and create a new tag + +### You need to update a release + +If you need to add or replace binaries: +1. Go to the release page on GitHub +2. Click "Edit release" +3. You can upload new files or delete existing ones +4. Click "Update release" + +### You tagged the wrong commit + +**Fix**: +1. Delete the tag locally: `git tag -d vX.X.X` +2. Delete the tag remotely: `git push origin :refs/tags/vX.X.X` +3. Check out the correct commit: `git checkout ` +4. Create the tag: `git tag vX.X.X` +5. Push the tag: `git push origin vX.X.X` + +Note: If the automated release was already created, you'll need to delete it from GitHub's releases page first. + +## Version numbering + +We follow [Semantic Versioning](https://semver.org/): + +- **MAJOR** version (X.0.0): Incompatible API changes +- **MINOR** version (0.X.0): New functionality in a backward compatible manner +- **PATCH** version (0.0.X): Backward compatible bug fixes + +## Publishing to crates.io + +The automated workflow does NOT publish to crates.io. To publish to crates.io: + +```bash +cargo publish +``` + +You'll need appropriate credentials configured for crates.io. + diff --git a/deny.toml b/deny.toml new file mode 100644 index 00000000..cfe551db --- /dev/null +++ b/deny.toml @@ -0,0 +1,244 @@ +# This template contains all of the possible sections and their default values + +# Note that all fields that take a lint level have these possible values: +# * deny - An error will be produced and the check will fail +# * warn - A warning will be produced, but the check will not fail +# * allow - No warning or error will be produced, though in some cases a note +# will be + +# The values provided in this template are the default values that will be used +# when any section or field is not specified in your own configuration + +# Root options + +# The graph table configures how the dependency graph is constructed and thus +# which crates the checks are performed against +[graph] +# If 1 or more target triples (and optionally, target_features) are specified, +# only the specified targets will be checked when running `cargo deny check`. +# This means, if a particular package is only ever used as a target specific +# dependency, such as, for example, the `nix` crate only being used via the +# `target_family = "unix"` configuration, that only having windows targets in +# this list would mean the nix crate, as well as any of its exclusive +# dependencies not shared by any other crates, would be ignored, as the target +# list here is effectively saying which targets you are building for. +targets = [ + # The triple can be any string, but only the target triples built in to + # rustc (as of 1.40) can be checked against actual config expressions + #"x86_64-unknown-linux-musl", + # You can also specify which target_features you promise are enabled for a + # particular target. target_features are currently not validated against + # the actual valid features supported by the target architecture. + #{ triple = "wasm32-unknown-unknown", features = ["atomics"] }, +] +# When creating the dependency graph used as the source of truth when checks are +# executed, this field can be used to prune crates from the graph, removing them +# from the view of cargo-deny. This is an extremely heavy hammer, as if a crate +# is pruned from the graph, all of its dependencies will also be pruned unless +# they are connected to another crate in the graph that hasn't been pruned, +# so it should be used with care. The identifiers are [Package ID Specifications] +# (https://doc.rust-lang.org/cargo/reference/pkgid-spec.html) +#exclude = [] +# If true, metadata will be collected with `--all-features`. Note that this can't +# be toggled off if true, if you want to conditionally enable `--all-features` it +# is recommended to pass `--all-features` on the cmd line instead +all-features = false +# If true, metadata will be collected with `--no-default-features`. The same +# caveat with `all-features` applies +no-default-features = false +# If set, these feature will be enabled when collecting metadata. If `--features` +# is specified on the cmd line they will take precedence over this option. +#features = [] + +# The output table provides options for how/if diagnostics are outputted +[output] +# When outputting inclusion graphs in diagnostics that include features, this +# option can be used to specify the depth at which feature edges will be added. +# This option is included since the graphs can be quite large and the addition +# of features from the crate(s) to all of the graph roots can be far too verbose. +# This option can be overridden via `--feature-depth` on the cmd line +feature-depth = 1 + +# This section is considered when running `cargo deny check advisories` +# More documentation for the advisories section can be found here: +# https://embarkstudios.github.io/cargo-deny/checks/advisories/cfg.html +[advisories] +# The path where the advisory databases are cloned/fetched into +#db-path = "$CARGO_HOME/advisory-dbs" +# The url(s) of the advisory databases to use +#db-urls = ["https://github.com/rustsec/advisory-db"] +# A list of advisory IDs to ignore. Note that ignored advisories will still +# output a note when they are encountered. +ignore = [ + #"RUSTSEC-0000-0000", + #{ id = "RUSTSEC-0000-0000", reason = "you can specify a reason the advisory is ignored" }, + #"a-crate-that-is-yanked@0.1.1", # you can also ignore yanked crate versions if you wish + #{ crate = "a-crate-that-is-yanked@0.1.1", reason = "you can specify why you are ignoring the yanked crate" }, +] +# If this is true, then cargo deny will use the git executable to fetch advisory database. +# If this is false, then it uses a built-in git library. +# Setting this to true can be helpful if you have special authentication requirements that cargo-deny does not support. +# See Git Authentication for more information about setting up git authentication. +#git-fetch-with-cli = true + +# This section is considered when running `cargo deny check licenses` +# More documentation for the licenses section can be found here: +# https://embarkstudios.github.io/cargo-deny/checks/licenses/cfg.html +[licenses] +# List of explicitly allowed licenses +# See https://spdx.org/licenses/ for list of possible licenses +# [possible values: any SPDX 3.11 short identifier (+ optional exception)]. +allow = [ + "MIT", + "Apache-2.0", + "Apache-2.0 WITH LLVM-exception", + "BSD-2-Clause", + "BSD-3-Clause", + "ISC", + "Unicode-3.0", + "MPL-2.0", + "CC0-1.0", + "Zlib", +] +# The confidence threshold for detecting a license from license text. +# The higher the value, the more closely the license text must be to the +# canonical license text of a valid SPDX license file. +# [possible values: any between 0.0 and 1.0]. +confidence-threshold = 0.8 +# Allow 1 or more licenses on a per-crate basis, so that particular licenses +# aren't accepted for every possible crate as with the normal allow list +exceptions = [ + # Each entry is the crate and version constraint, and its specific allow + # list + #{ allow = ["Zlib"], crate = "adler32" }, +] + +# Some crates don't have (easily) machine readable licensing information, +# adding a clarification entry for it allows you to manually specify the +# licensing information +#[[licenses.clarify]] +# The package spec the clarification applies to +#crate = "ring" +# The SPDX expression for the license requirements of the crate +#expression = "MIT AND ISC AND OpenSSL" +# One or more files in the crate's source used as the "source of truth" for +# the license expression. If the contents match, the clarification will be used +# when running the license check, otherwise the clarification will be ignored +# and the crate will be checked normally, which may produce warnings or errors +# depending on the rest of your configuration +#license-files = [ +# Each entry is a crate relative path, and the (opaque) hash of its contents +#{ path = "LICENSE", hash = 0xbd0eed23 } +#] + +[licenses.private] +# If true, ignores workspace crates that aren't published, or are only +# published to private registries. +# To see how to mark a crate as unpublished (to the official registry), +# visit https://doc.rust-lang.org/cargo/reference/manifest.html#the-publish-field. +ignore = false +# One or more private registries that you might publish crates to, if a crate +# is only published to private registries, and ignore is true, the crate will +# not have its license(s) checked +registries = [ + #"https://sekretz.com/registry +] + +# This section is considered when running `cargo deny check bans`. +# More documentation about the 'bans' section can be found here: +# https://embarkstudios.github.io/cargo-deny/checks/bans/cfg.html +[bans] +# Lint level for when multiple versions of the same crate are detected +multiple-versions = "warn" +# Lint level for when a crate version requirement is `*` +wildcards = "allow" +# The graph highlighting used when creating dotgraphs for crates +# with multiple versions +# * lowest-version - The path to the lowest versioned duplicate is highlighted +# * simplest-path - The path to the version with the fewest edges is highlighted +# * all - Both lowest-version and simplest-path are used +highlight = "all" +# The default lint level for `default` features for crates that are members of +# the workspace that is being checked. This can be overridden by allowing/denying +# `default` on a crate-by-crate basis if desired. +workspace-default-features = "allow" +# The default lint level for `default` features for external crates that are not +# members of the workspace. This can be overridden by allowing/denying `default` +# on a crate-by-crate basis if desired. +external-default-features = "allow" +# List of crates that are allowed. Use with care! +allow = [ + #"ansi_term@0.11.0", + #{ crate = "ansi_term@0.11.0", reason = "you can specify a reason it is allowed" }, +] +# List of crates to deny +deny = [ + #"ansi_term@0.11.0", + #{ crate = "ansi_term@0.11.0", reason = "you can specify a reason it is banned" }, + # Wrapper crates can optionally be specified to allow the crate when it + # is a direct dependency of the otherwise banned crate + #{ crate = "ansi_term@0.11.0", wrappers = ["this-crate-directly-depends-on-ansi_term"] }, +] + +# List of features to allow/deny +# Each entry the name of a crate and a version range. If version is +# not specified, all versions will be matched. +#[[bans.features]] +#crate = "reqwest" +# Features to not allow +#deny = ["json"] +# Features to allow +#allow = [ +# "rustls", +# "__rustls", +# "__tls", +# "hyper-rustls", +# "rustls", +# "rustls-pemfile", +# "rustls-tls-webpki-roots", +# "tokio-rustls", +# "webpki-roots", +#] +# If true, the allowed features must exactly match the enabled feature set. If +# this is set there is no point setting `deny` +#exact = true + +# Certain crates/versions that will be skipped when doing duplicate detection. +skip = [ + #"ansi_term@0.11.0", + #{ crate = "ansi_term@0.11.0", reason = "you can specify a reason why it can't be updated/removed" }, +] +# Similarly to `skip` allows you to skip certain crates during duplicate +# detection. Unlike skip, it also includes the entire tree of transitive +# dependencies starting at the specified crate, up to a certain depth, which is +# by default infinite. +skip-tree = [ + #"ansi_term@0.11.0", # will be skipped along with _all_ of its direct and transitive dependencies + #{ crate = "ansi_term@0.11.0", depth = 20 }, +] + +# This section is considered when running `cargo deny check sources`. +# More documentation about the 'sources' section can be found here: +# https://embarkstudios.github.io/cargo-deny/checks/sources/cfg.html +[sources] +# Lint level for what to happen when a crate from a crate registry that is not +# in the allow list is encountered +unknown-registry = "warn" +# Lint level for what to happen when a crate from a git repository that is not +# in the allow list is encountered +unknown-git = "warn" +# List of URLs for allowed crate registries. Defaults to the crates.io index +# if not specified. If it is specified but empty, no registries are allowed. +allow-registry = ["https://github.com/rust-lang/crates.io-index"] +# List of URLs for allowed Git repositories +allow-git = [ + "https://github.com/faradayio/compose_yml", +] + +[sources.allow-org] +# github.com organizations to allow git sources for +github = [] +# gitlab.com organizations to allow git sources for +gitlab = [] +# bitbucket.org organizations to allow git sources for +bitbucket = [] diff --git a/src/args/opts.rs b/src/args/opts.rs index 91c71b2c..60b6fa3f 100644 --- a/src/args/opts.rs +++ b/src/args/opts.rs @@ -72,7 +72,7 @@ pub struct Process { /// An optional user as whom we should run the command. /// /// TODO LOW: Is this technically "user[:group]"? If so, we need - /// support for that type in `compose_yml` and use it here. + /// support for that type in `faraday_compose_yml` and use it here. pub user: Option, /// Should we allocate a TTY when executing the command? diff --git a/src/cli.yml b/src/cli.yml deleted file mode 100644 index a7b0b035..00000000 --- a/src/cli.yml +++ /dev/null @@ -1,290 +0,0 @@ -name: "cage" -global_settings: - - "VersionlessSubcommands" - - "ColoredHelp" -settings: - - "SubcommandRequiredElseHelp" -args: - - project-name: - short: "p" - long: "project-name" - value_name: "PROJECT_NAME" - help: "The name of this project. Defaults to the current directory name." - - target: - long: "target" - value_name: "TARGET" - help: "Override settings with values from the specified subdirectory of `pods/targets`. Defaults to `development` unless running tests." - - default-tags: - long: "default-tags" - value_name: "TAG_FILE" - help: "A list of tagged image names, one per line, to be used as defaults for images." -about: "Develop complex projects with lots of Docker services" -after_help: | - To create a new project: - - cage new myproj - - From inside a project directory: - - cage pull # Download images for the a project - cage up --init # Start the app, initializing the database - cage status # Get an overview of the project - - Access your application at http://localhost:3000/. To download and edit - the source code for your application, run: - - cage source ls # List available service source code - cage source mount rails_hello # Clone source and configure mounts - cage up # Restart any affected services - cage status # See how things have changed - - Now create `src/rails_hello/public/index.html` and reload in your browser. - - Cage is copyright 2016 by Faraday, Inc., and distributed under either the - Apache 2.0 or MIT license. For more information, see - https://github.com/faradayio/cage. -subcommands: - - sysinfo: - about: "Print information about the system" - # Hide this for now until we decide what form it should take. - hidden: true - - new: - about: "Create a directory containing a new project" - args: - - NAME: - value_name: "NAME" - required: true - help: "The name of the new project" - - status: - about: "Print out the status of the current project" - args: - - POD_OR_SERVICE: &pod_or_service - value_name: "POD_OR_SERVICE" - multiple: true - help: "Pod or service names. Defaults to all." - - build: - about: "Build images for the containers associated with this project" - args: - - POD_OR_SERVICE: *pod_or_service - - pull: - about: "Build images for the containers associated with this project" - args: - - quiet: - long: "quiet" - short: "q" - help: "Don't show download progress" - - POD_OR_SERVICE: *pod_or_service - - up: - about: "Run project" - args: - - init: - long: "init" - help: "Run any pod initialization commands (for first startup)" - - POD_OR_SERVICE: *pod_or_service - - restart: - about: "Restart all services associated with this project" - args: - - POD_OR_SERVICE: *pod_or_service - - stop: - about: "Stop all containers associated with this project" - args: - - POD_OR_SERVICE: *pod_or_service - - rm: - about: "Remove the containers associated with a pod or service" - args: - - force: - short: "f" - long: "force" - help: "Remove without confirming first" - - remove-volumes: - short: "v" - help: "Remove anonymous volumes associated with containers" - - POD_OR_SERVICE: *pod_or_service - - run: - about: "Run a specific pod as a one-shot task" - settings: - - "TrailingVarArg" - args: - - detached: &detached - short: "d" - help: "Run command detached in background" - - user: &user - long: "user" - value_name: "USER" - help: "User as which to run a command" - - no-allocate-tty: ¬ty - short: "T" - help: "Do not allocate a TTY when running a command" - - entrypoint: &entrypoint - long: "entrypoint" - value_name: "ENTRYPOINT" - help: "Override the entrypoint of the service" - - environment: &environment - short: "e" - value_names: ["KEY", "VAL"] - multiple: true - number_of_values: 2 - value_delimiter: "=" - help: "Set an environment variable in the container" - - SERVICE: &service - value_name: "SERVICE" - required: true - help: "The name of the service, either as `pod/service`, or as just `service` if unique" - - COMMAND: &command - value_name: "COMMAND" - required: false - multiple: true - help: "The command to run, with any arguments" - - run-script: - about: "Run a named script defined in metadata for specified pods or services" - args: - - no-deps: &nodeps - long: "--no-deps" - help: "Do not start linked services when running scripts" - - SCRIPT_NAME: - value_name: "SCRIPT_NAME" - required: true - help: "The named script to run" - - POD_OR_SERVICE: *pod_or_service - - exec: - about: "Run a command inside an existing container" - settings: - - "TrailingVarArg" - args: - - detached: *detached - - user: *user - - no-allocate-tty: *notty - - privileged: &privileged - long: "privileged" - help: "Run a command with elevated privileges" - - SERVICE: *service - - COMMAND: - value_name: "COMMAND" - required: true - multiple: true - help: "The command to run, with any arguments" - - shell: - about: "Run an interactive shell inside a running container" - args: - - detached: *detached - - user: *user - - no-allocate-tty: *notty - - privileged: *privileged - - SERVICE: *service - - test: - about: "Run the tests associated with a service, if any" - settings: - - "TrailingVarArg" - args: - - export-test-output: - long: "--export-test-output" - help: "Copy container's $WORKDIR/test_output to $PROJECT_DIR/test_output" - - SERVICE: *service - - COMMAND: *command - after_help: | - To enable tests for a service, add a label with the test command. - Assuming your service uses rspec, this might look like: - - myservice: - labels: - io.fdy.cage.test: "rspec" - - Run this test command using: - - cage test myservice - - To run only a subset of your tests, you can also pass a custom test - command: - - cage test myservice rspec spec/my_new_feature_spec.rb - - - logs: - about: "Display logs for a service" - args: - - follow: - short: "f" - help: "Follow log output" - - number: - long: "tail" - value_name: "NUMBER" - help: "Number of lines from end of output to display" - - POD_OR_SERVICE: *pod_or_service - - - source: - about: "Commands for working with git repositories and local source trees" - settings: - - "SubcommandRequiredElseHelp" - subcommands: - - ls: - about: "List all known source tree aliases and URLs" - - clone: - about: "Clone a git repository using its short alias and mount it into the containers that use it" - args: - - ALIAS: - value_name: "ALIAS" - required: true - help: "The short alias of the repo to clone (see `source list`)" - - mount: - about: "Mount a source tree into the containers that use it" - args: &mount_args - - ALIASES: - value_name: "ALIASES" - multiple: true - min_values: 1 - help: "The short aliases of the source trees to operate on (see `source list`)" - - ALL: - long: "all" - short: "a" - help: "Operate on all source trees" - groups: &mount_groups - - sources: - # Make these arguments mutally exclusive. - args: - - ALIASES - - ALL - required: true - - unmount: - about: "Unmount a local source tree from all containers" - args: *mount_args - groups: *mount_groups - - generate: - about: "Commands for generating new source files" - settings: - - "SubcommandRequiredElseHelp" - subcommands: - - completion: - about: "Generate shell autocompletion support" - args: - - SHELL: - value_name: "SHELL" - possible_values: - - "bash" - - "fish" - required: true - help: "The name of shell for which to generate an autocompletion script" - after_help: | - To set up shell auto-completion for bash: - - cage generate completion bash - source cage.bash-completion - - And set up your ~/.profile or ~/.bash_profile to source this file on - each login. - - To set up shell auto-completion for fish: - - cage generate completion fish - source cage.fish - mkdir -p ~/.config/fish/completions - mv cage.fish ~/.config/fish/completions - - secrets: - about: "Generate config/secrets.yml for local secret storage" - - vault: - about: "Generate config/vault.yml for fetching secrets from vault" - - export: - about: "Export project as flattened *.yml files" - args: - - DIR: - value_name: "DIR" - required: true - help: "The name of the directory to create" diff --git a/src/cmd/generate.rs b/src/cmd/generate.rs index b945a1fa..a9f33766 100644 --- a/src/cmd/generate.rs +++ b/src/cmd/generate.rs @@ -72,6 +72,19 @@ impl CommandGenerate for Project { target_tmpl.generate(&dir, &target_info, &mut io::stdout())?; } + // Generate production target using its specific template. + let mut production_tmpl = Template::new("new/pods/targets/production")?; + let production_info = TargetInfo { + project: &proj_info, + name: "production", + }; + let production_dir = targets_dir.join("production"); + production_tmpl.generate( + &production_dir, + &production_info, + &mut io::stdout(), + )?; + Ok(proj_dir) } diff --git a/src/cmd/logs.rs b/src/cmd/logs.rs index b66fe760..e1c51fef 100644 --- a/src/cmd/logs.rs +++ b/src/cmd/logs.rs @@ -35,7 +35,9 @@ impl CommandLogs for Project { args::ActOn::Named(ref names) if names.len() == 1 => { self.compose(runner, "logs", act_on, opts) } - _ => Err("You may only specify a single service or pod".into()), + _ => Err(anyhow::anyhow!( + "You may only specify a single service or pod" + )), } } } diff --git a/src/cmd/run.rs b/src/cmd/run.rs index 89eb1ad4..6ed20ff5 100644 --- a/src/cmd/run.rs +++ b/src/cmd/run.rs @@ -88,8 +88,7 @@ impl CommandRun for Project { let sources_dirs = self.sources_dirs(); let mount_count = sources .iter() - .cloned() - .filter(|ref source_mount| { + .filter(|&source_mount| { source_mount.source.is_available_locally(&sources_dirs) && source_mount.source.mounted() }) @@ -129,7 +128,7 @@ impl CommandRun for Project { // Don't clobber any existing output. if test_output_path.exists() { - return Err(ErrorKind::OutputDirectoryExists(test_output_path).into()); + return Err(Error::OutputDirectoryExists(test_output_path).into()); } runner diff --git a/src/cmd/run_script.rs b/src/cmd/run_script.rs index 710b8272..5a949ebd 100644 --- a/src/cmd/run_script.rs +++ b/src/cmd/run_script.rs @@ -38,14 +38,14 @@ impl CommandRunScript for Project { match pod_or_service? { PodOrService::Pod(pod) => { // Ignore any pods that aren't enabled in the current target - if pod.enabled_in(&target) { + if pod.enabled_in(target) { for service_name in pod.service_names() { pod.run_script( runner, - &self, - &service_name, - &script_name, - &opts, + self, + service_name, + script_name, + opts, )?; } } @@ -53,14 +53,8 @@ impl CommandRunScript for Project { PodOrService::Service(pod, service_name) => { // Don't run this on any service whose pod isn't enabled in // the current target - if pod.enabled_in(&target) { - pod.run_script( - runner, - &self, - &service_name, - &script_name, - &opts, - )?; + if pod.enabled_in(target) { + pod.run_script(runner, self, service_name, script_name, opts)?; } } } diff --git a/src/cmd/source.rs b/src/cmd/source.rs index 80de4036..d3d49760 100644 --- a/src/cmd/source.rs +++ b/src/cmd/source.rs @@ -65,7 +65,7 @@ impl CommandSource for Project { let source = self .sources_mut() .find_by_alias_mut(alias) - .ok_or_else(|| ErrorKind::UnknownSource(alias.to_owned()))?; + .ok_or_else(|| Error::UnknownSource(alias.to_owned()))?; if !source.is_available_locally(&sources_dirs) { source.clone_source(runner, &sources_dirs)?; } else { diff --git a/src/cmd/status.rs b/src/cmd/status.rs index 64b2a837..d9a2272c 100644 --- a/src/cmd/status.rs +++ b/src/cmd/status.rs @@ -1,7 +1,7 @@ //! The `status` command. use colored::*; -use compose_yml::v2 as dc; +use faraday_compose_yml::v2 as dc; use crate::args; use crate::command_runner::CommandRunner; diff --git a/src/cmd/up.rs b/src/cmd/up.rs index 2bdd927d..4923e6b8 100644 --- a/src/cmd/up.rs +++ b/src/cmd/up.rs @@ -80,25 +80,20 @@ impl CommandUp for Project { ); loop { let state: RuntimeState = RuntimeState::for_project(self)?; - let listening = pod - .service_names() - .iter() - .map(|service_name| { - debug!("scanning service '{}'", service_name); - let containers = state.service_containers(service_name); - if containers.is_empty() { - // No containers visible yet; give Docker time. - debug!("no containers for service '{}' yet", service_name); - false - } else { - // If we have at least one container, scan it. - containers - .iter() - .map(|container| container.is_listening_to_ports()) - .all(|listening| listening) - } - }) - .all(|listening| listening); + let listening = pod.service_names().iter().all(|service_name| { + debug!("scanning service '{}'", service_name); + let containers = state.service_containers(service_name); + if containers.is_empty() { + // No containers visible yet; give Docker time. + debug!("no containers for service '{}' yet", service_name); + false + } else { + // If we have at least one container, scan it. + containers + .iter() + .all(|container| container.is_listening_to_ports()) + } + }); if listening { break; } @@ -109,9 +104,10 @@ impl CommandUp for Project { println!("Initializing pod '{}'", pod.name()); for cmd in pod.run_on_init() { if cmd.is_empty() { - return Err("all `run_on_init` items for '{}' \ - must have at least one value" - .into()); + return Err(anyhow::anyhow!( + "all `run_on_init` items for '{}' must have at least one value", + pod.name() + )); } let service = &cmd[0]; let cmd = if cmd.len() >= 2 { diff --git a/src/command_runner.rs b/src/command_runner.rs index 9a31bc66..48579ffc 100644 --- a/src/command_runner.rs +++ b/src/command_runner.rs @@ -55,12 +55,12 @@ pub trait Command { if status.success() { Ok(()) } else { - Err(self.command_failed_error().into()) + Err(self.command_failed_error()) } } /// Make an error representing a failure of this command. - fn command_failed_error(&self) -> ErrorKind; + fn command_failed_error(&self) -> anyhow::Error; } /// Support for running operating system commands. @@ -135,13 +135,13 @@ impl Command for OsCommand { fn status(&mut self) -> Result { debug!("Running {:?}", &self.arg_log); - self.command - .status() - .chain_err(|| self.command_failed_error()) + self.command.status().map_err(|e| { + anyhow::Error::new(e).context(Error::CommandFailed(self.arg_log.clone())) + }) } - fn command_failed_error(&self) -> ErrorKind { - ErrorKind::CommandFailed(self.arg_log.clone()) + fn command_failed_error(&self) -> anyhow::Error { + Error::CommandFailed(self.arg_log.clone()).into() } } @@ -238,13 +238,13 @@ impl Command for TestCommand { // There's no portable way to build an `ExitStatus` in portable // Rust without actually running a command, so just choose an // inoffensive one with the result we want. - process::Command::new("true") - .status() - .chain_err(|| self.command_failed_error()) + process::Command::new("true").status().map_err(|e| { + anyhow::Error::new(e).context(Error::CommandFailed(self.cmd.clone())) + }) } - fn command_failed_error(&self) -> ErrorKind { - ErrorKind::CommandFailed(self.cmd.clone()) + fn command_failed_error(&self) -> anyhow::Error { + Error::CommandFailed(self.cmd.clone()).into() } } @@ -275,7 +275,7 @@ macro_rules! assert_ran { } #[test] -pub fn test_command_runner_logs_commands() { +fn test_command_runner_logs_commands() { let runner = TestCommandRunner::new(); let exit_code = runner diff --git a/src/default_tags.rs b/src/default_tags.rs index 5d5cd99f..7012705f 100644 --- a/src/default_tags.rs +++ b/src/default_tags.rs @@ -1,7 +1,7 @@ //! Tools for working with lists of image tags (versions) provided by an //! external source. -use compose_yml::v2 as dc; +use faraday_compose_yml::v2 as dc; use std::collections::btree_map; use std::collections::BTreeMap; use std::io::{self, BufRead}; diff --git a/src/errors.rs b/src/errors.rs index dce3dc9a..69307079 100644 --- a/src/errors.rs +++ b/src/errors.rs @@ -1,167 +1,96 @@ -//! We provide fancy error-handling support thanks to the [`error_chain` -//! crate][error_chain]. The primary advantage of `error_chain` is that it -//! provides support for backtraces. The secondary advantage of this crate -//! is that it gives us nice, structured error types. +//! We provide fancy error-handling support thanks to the [`anyhow` +//! crate][anyhow]. The primary advantage of `anyhow` is that it +//! provides support for backtraces (when available) and easy error context. //! -//! [error_chain]: https://github.com/brson/error-chain +//! [anyhow]: https://github.com/dtolnay/anyhow #![allow(missing_docs, clippy::redundant_closure)] -use compose_yml::v2 as dc; use std::ffi::OsString; -use std::io; -use std::path::{PathBuf, StripPrefixError}; -use std::string::FromUtf8Error; +use std::path::PathBuf; +use thiserror::Error; use crate::project::PROJECT_CONFIG_PATH; use crate::version; -// TODO: Replace `error-chain` with `anyhow` as soon as backtraces stablize. -error_chain! { - // TODO HIGH: Most of these will go away as we convert them to more - // meaningful errors. - foreign_links { - Compose(dc::Error); - Docker(boondock::errors::Error); - Utf8Error(FromUtf8Error); - Glob(glob::GlobError); - GlobPattern(glob::PatternError); - Io(io::Error); - StripPrefix(StripPrefixError); - } +pub type Result = anyhow::Result; - errors { - /// An error occurred running an external command. - CommandFailed(command: Vec) { - description("error running external command") - display("error running '{}'", command_to_string(&command)) - } +#[derive(Debug, Error)] +pub enum Error { + #[error("error running '{}'", command_to_string(.0))] + CommandFailed(Vec), - /// We could not look up our project's `RuntimeState` using Docker. - CouldNotGetRuntimeState { - description("error getting the project's state from Docker") - display("error getting the project's state from Docker") - } + #[error("error getting the project's state from Docker")] + CouldNotGetRuntimeState, - /// We failed to parse a string. - CouldNotParse(parsing_as: &'static str, input: String) { - description("failed to parse string") - display("failed to parse '{}' as {}", &input, parsing_as) - } + #[error("failed to parse '{}' as {}", .input, .parsing_as)] + CouldNotParse { + parsing_as: &'static str, + input: String, + }, - /// An error occurred reading a directory. - CouldNotReadDirectory(path: PathBuf) { - description("could not read a directory") - display("could not read '{}'", path.display()) - } + #[error("could not read '{}'", .0.display())] + CouldNotReadDirectory(PathBuf), - /// An error occurred reading a file. - CouldNotReadFile(path: PathBuf) { - description("could not read a file") - display("could not read '{}'", path.display()) - } + #[error("could not read '{}'", .0.display())] + CouldNotReadFile(PathBuf), - /// An error occurred writing a file. - CouldNotWriteFile(path: PathBuf) { - description("could not write to a file") - display("could not write to '{}'", path.display()) - } + #[error("could not write to '{}'", .0.display())] + CouldNotWriteFile(PathBuf), - /// A feature was disabled at compile time. - FeatureDisabled { - description("feature disabled at compile time") - display("this feature was disabled when the application was \ - compiled (you may want to rebuild from source)") - } + #[error("this feature was disabled when the application was compiled (you may want to rebuild from source)")] + FeatureDisabled, - /// This project specified that it required a different version of - /// this tool. - MismatchedVersion(required: semver::VersionReq) { - description("incompatible cage version") - display("{} specifies cage {}, but you have {}", - PROJECT_CONFIG_PATH.display(), &required, version()) - } + #[error("{} specifies cage_version {}, but you have {}", PROJECT_CONFIG_PATH.display(), .0, version())] + MismatchedVersion(semver::VersionReq), - /// An output directory already exists, and would be overwritten. - OutputDirectoryExists(path: PathBuf) { - description("output directory already exists") - display("output directory {} already exists (please delete)", path.display()) - } + #[error("output directory {} already exists (please delete)", .0.display())] + OutputDirectoryExists(PathBuf), - /// An error occurred applying a plugin. - PluginFailed(plugin: String) { - description("plugin failed") - display("plugin '{}' failed", &plugin) - } + #[error("plugin '{}' failed", .0)] + PluginFailed(String), - /// An target file tried to add new services that weren't present in - /// the file it was overriding. - ServicesAddedInTarget(base: PathBuf, target: PathBuf, names: Vec) { - description("services present in target but not in base") - display("services {:?} present in {} but not in {}", - &names, base.display(), target.display()) - } + #[error("services {:?} present in {} but not in {}", .names, .base.display(), .target.display())] + ServicesAddedInTarget { + base: PathBuf, + target: PathBuf, + names: Vec, + }, - /// The user tried to access an undefined library. - /// - /// TODO LOW: This will be merged with `UnknownSource` when library - /// keys are merged with source repo aliases. - UnknownLibKey(lib_key: String) { - description("unknown library") - display("no library '{}' defined in `config/sources.yml`", &lib_key) - } + #[error("no library '{}' defined in `config/sources.yml`", .0)] + UnknownLibKey(String), - /// The user tried to specify a repo subdirectory on a library - LibHasRepoSubdirectory(lib_key: String) { - description("invalid library context URL") - display("library '{}' may not specify a subdirectory in its git URL", &lib_key) - } + #[error("library '{}' may not specify a subdirectory in its git URL", .0)] + LibHasRepoSubdirectory(String), - /// The requested target does not appear to exist. - UnknownTarget(target_name: String) { - description("unknown target") - display("unknown target '{}'", &target_name) - } + #[error("unknown target '{}'", .0)] + UnknownTarget(String), - /// The requested pod or service does not appear to exist. - UnknownPodOrService(pod_or_service_name: String) { - description("unknown pod or service") - display("unknown pod or service '{}'", &pod_or_service_name) - } + #[error("unknown pod or service '{}'", .0)] + UnknownPodOrService(String), - /// The requested service does not appear to exist. - UnknownService(service_name: String) { - description("unknown service") - display("unknown service '{}'", &service_name) - } + #[error("unknown service '{}'", .0)] + UnknownService(String), - /// The requested source alias does not appear to exist. - UnknownSource(source_alias: String) { - description("unknown source alias") - display("unknown short alias '{}' for source tree (try `cage \ - source ls`)", - &source_alias) - } + #[error("unknown short alias '{}' for source tree (try `cage source ls`)", .0)] + UnknownSource(String), - /// We were unable to communicate with the specified Vault server. - VaultError(url: String) { - description("an error occurred talking to a Vault server") - display("an error occurred talking to the Vault server at {}", &url) - } - } + #[error("an error occurred talking to the Vault server at {}", .0)] + VaultError(String), } -impl ErrorKind { - /// Build an `ErrorKind::CouldNotParse` value. - pub fn parse(parsing_as: &'static str, input: S) -> ErrorKind +impl Error { + pub fn parse(parsing_as: &'static str, input: S) -> Error where S: Into, { - ErrorKind::CouldNotParse(parsing_as, input.into()) + Error::CouldNotParse { + parsing_as, + input: input.into(), + } } } -/// Convert a command-line into a string. fn command_to_string(command: &[OsString]) -> String { let cmd: Vec<_> = command .iter() diff --git a/src/ext/context.rs b/src/ext/context.rs index 58fe5d48..d0693883 100644 --- a/src/ext/context.rs +++ b/src/ext/context.rs @@ -1,6 +1,6 @@ -//! Extension methods for `compose_yml::v2::Service`. +//! Extension methods for `faraday_compose_yml::v2::Service`. -use compose_yml::v2 as dc; +use faraday_compose_yml::v2 as dc; use std::path::Path; use crate::errors::*; diff --git a/src/ext/git_url.rs b/src/ext/git_url.rs index 858a9695..f63a8c2e 100644 --- a/src/ext/git_url.rs +++ b/src/ext/git_url.rs @@ -1,6 +1,6 @@ -//! Extension methods for `compose_yml::v2::GitUrl`. +//! Extension methods for `faraday_compose_yml::v2::GitUrl`. -use compose_yml::v2 as dc; +use faraday_compose_yml::v2 as dc; use std::ffi::OsString; use crate::errors::*; diff --git a/src/ext/port_mapping.rs b/src/ext/port_mapping.rs index 6c27c85b..0429c6cc 100644 --- a/src/ext/port_mapping.rs +++ b/src/ext/port_mapping.rs @@ -1,6 +1,6 @@ -//! Extension methods for `compose_yml::v2::PortMapping`. +//! Extension methods for `faraday_compose_yml::v2::PortMapping`. -use compose_yml::v2 as dc; +use faraday_compose_yml::v2 as dc; /// These methods will appear as regular methods on `PortMapping` in any /// module which includes `PortMappingExt`. diff --git a/src/ext/service.rs b/src/ext/service.rs index 84c14e6d..f42b2b56 100644 --- a/src/ext/service.rs +++ b/src/ext/service.rs @@ -1,6 +1,6 @@ -//! Extension methods for `compose_yml::v2::Service`. +//! Extension methods for `faraday_compose_yml::v2::Service`. -use compose_yml::v2 as dc; +use faraday_compose_yml::v2 as dc; use std::vec; use crate::errors::*; @@ -40,8 +40,7 @@ pub trait ServiceExt { /// `Service` object, so you can use it to decide how you want to /// update other fields of this object without running afoul of the /// borrow checker. - fn sources<'a, 'b>(&'a self, sources: &'b sources::Sources) - -> Result>; + fn sources<'b>(&self, sources: &'b sources::Sources) -> Result>; } impl ServiceExt for dc::Service { @@ -90,10 +89,7 @@ impl ServiceExt for dc::Service { } } - fn sources<'a, 'b>( - &'a self, - sources: &'b sources::Sources, - ) -> Result> { + fn sources<'b>(&self, sources: &'b sources::Sources) -> Result> { // Get our `context`, if any. let container_path = self.source_mount_dir()?; let source_subdirectory = self.repository_subdirectory()?; @@ -118,10 +114,11 @@ impl ServiceExt for dc::Service { for (label, mount_as) in &self.labels { let prefix = "io.fdy.cage.lib."; if let Some(lib_name) = label.strip_prefix(prefix) { - let source = - sources.find_by_lib_key(lib_name).ok_or_else(|| -> Error { - ErrorKind::UnknownLibKey(lib_name.to_string()).into() - })?; + let source = sources.find_by_lib_key(lib_name).ok_or_else( + || -> anyhow::Error { + Error::UnknownLibKey(lib_name.to_string()).into() + }, + )?; libs.push(SourceMount { container_path: mount_as.value()?.to_owned(), diff --git a/src/hook.rs b/src/hook.rs index 7d13a527..48e5836a 100644 --- a/src/hook.rs +++ b/src/hook.rs @@ -58,17 +58,20 @@ impl HookManager { return Ok(()); } - let mkerr = || ErrorKind::CouldNotReadDirectory(d_dir.clone()); - // Find all our hook scripts and alphabetize them. let mut scripts = vec![]; - for entry in fs::read_dir(&d_dir).chain_err(&mkerr)? { - let entry = entry.chain_err(&mkerr)?; + for entry in fs::read_dir(&d_dir).map_err(|e| { + anyhow::Error::new(e).context(Error::CouldNotReadDirectory(d_dir.clone())) + })? { + let entry = entry.map_err(|e| { + anyhow::Error::new(e) + .context(Error::CouldNotReadDirectory(d_dir.clone())) + })?; let path = entry.path(); trace!("Checking {} to see if it's a hook", path.display()); - let ty = entry - .file_type() - .chain_err(|| ErrorKind::CouldNotReadFile(path.clone()))?; + let ty = entry.file_type().map_err(|e| { + anyhow::Error::new(e).context(Error::CouldNotReadFile(path.clone())) + })?; let os_name = entry.file_name(); let name = os_name.to_str_or_err()?; if ty.is_file() && !name.starts_with('.') && name.ends_with(".hook") { diff --git a/src/lib.rs b/src/lib.rs index 16ab2684..a29090ad 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -14,7 +14,7 @@ //! //! ## Where to start //! -//! Cage relies heavily on the [`compose_yml`][compose_yml] crate, which +//! Cage relies heavily on the [`faraday_compose_yml`][compose_yml] crate, which //! represents a `docker-compose.yml` file. //! //! A good place to start reading through this API is the `Project` struct, @@ -24,7 +24,7 @@ //! You may also want to look the `plugins` module, which handles much of //! our code generation and YAML transformation. Essentially, cage works //! like a multi-pass "compiler", where the intermediate representation is -//! a `compose_yml::v2::File` object, and each transformation plugin is a +//! a `faraday_compose_yml::v2::File` object, and each transformation plugin is a //! analogous to a "pass" in a compiler. //! //! [cage]: http://cage.faraday.io/ @@ -43,11 +43,7 @@ clippy::all )] #![allow(clippy::field_reassign_with_default, clippy::unnecessary_wraps)] -// The `error_chain` documentation says we need this. -#![recursion_limit = "1024"] -#[macro_use] -extern crate error_chain; #[macro_use] extern crate lazy_static; #[macro_use] diff --git a/src/main.rs b/src/main.rs index 0c08792e..a877fb66 100644 --- a/src/main.rs +++ b/src/main.rs @@ -2,190 +2,587 @@ #![allow(clippy::field_reassign_with_default)] -#[macro_use] -extern crate clap; -#[macro_use] -extern crate log; - use cage::{ cmd::*, command_runner::{Command, CommandRunner, OsCommandRunner}, - ErrorKind, Project, Result, + Error, Project, Result, }; +use clap::{Parser, Subcommand, ValueEnum}; use colored::Colorize; use itertools::Itertools; use std::{ + collections::BTreeMap, env, fs, io::{self, Write}, path::Path, process, }; -use yaml_rust::yaml; - -/// Load our command-line interface definitions from an external `clap` -/// YAML file. We could create these using code, but at the cost of more -/// verbosity. -fn cli(yaml: &yaml::Yaml) -> clap::App<'_, '_> { - clap::App::from_yaml(yaml).version(crate_version!()) -} - -/// Custom methods we want to add to `clap::App`. -trait ArgMatchesExt { - /// Do we need to generate `.cage/pods`? This will probably be - /// refactored in the future. - fn should_output_project(&self) -> bool; - /// Get either the specified target name, or a reasonable default. - fn target_name(&self) -> &str; - - /// Determine what pods or services we're supposed to act on. - fn to_acts_on(&self, arg_name: &str, include_tasks: bool) -> cage::args::ActOn; - - /// Determine what sources we're supposed to act on. - fn to_acts_on_sources( - &self, - project: &Project, - ) -> Result; - - /// Extract options shared by `exec` and `run` from our command-line - /// arguments. - fn to_process_options(&self) -> cage::args::opts::Process; - - /// Extract `exec` options from our command-line arguments. - fn to_exec_options(&self) -> cage::args::opts::Exec; +#[macro_use] +extern crate log; - /// Extract `run` options from our command-line arguments. - fn to_run_options(&self) -> cage::args::opts::Run; +const AFTER_HELP: &str = r#"To create a new project: + + cage new myproj + +From inside a project directory: + + cage pull # Download images for the a project + cage up --init # Start the app, initializing the database + cage status # Get an overview of the project + +Access your application at http://localhost:3000/. To download and edit +the source code for your application, run: + + cage source ls # List available service source code + cage source mount rails_hello # Clone source and configure mounts + cage up # Restart any affected services + cage status # See how things have changed + +Now create `src/rails_hello/public/index.html` and reload in your browser. + +Cage is copyright 2016 by Faraday, Inc., and distributed under either the +Apache 2.0 or MIT license. For more information, see +https://github.com/faradayio/cage."#; + +#[derive(Parser, Debug)] +#[command(name = "cage", version, about = "Develop complex projects with lots of Docker services", after_help = AFTER_HELP)] +struct Cli { + #[arg( + short = 'p', + long = "project-name", + value_name = "PROJECT_NAME", + help = "The name of this project. Defaults to the current directory name." + )] + project_name: Option, + + #[arg( + long = "target", + value_name = "TARGET", + help = "Override settings with values from the specified subdirectory of `pods/targets`. Defaults to `development` unless running tests." + )] + target: Option, + + #[arg( + long = "default-tags", + value_name = "TAG_FILE", + help = "A list of tagged image names, one per line, to be used as defaults for images." + )] + default_tags: Option, + + #[command(subcommand)] + command: Commands, +} - /// Extract `test` options from our command-line arguments. - fn to_test_options(&self) -> cage::args::opts::Test; +#[derive(Subcommand, Debug)] +enum Commands { + #[command(about = "Print information about the system", hide = true)] + Sysinfo, + + #[command(about = "Create a directory containing a new project")] + New { + #[arg(value_name = "NAME", help = "The name of the new project")] + name: String, + }, + + #[command(about = "Print out the status of the current project")] + Status { + #[arg( + value_name = "POD_OR_SERVICE", + help = "Pod or service names. Defaults to all." + )] + pod_or_service: Vec, + }, + + #[command(about = "Build images for the containers associated with this project")] + Build { + #[arg( + value_name = "POD_OR_SERVICE", + help = "Pod or service names. Defaults to all." + )] + pod_or_service: Vec, + }, + + #[command(about = "Build images for the containers associated with this project")] + Pull { + #[arg(short = 'q', long = "quiet", help = "Don't show download progress")] + quiet: bool, + + #[arg( + value_name = "POD_OR_SERVICE", + help = "Pod or service names. Defaults to all." + )] + pod_or_service: Vec, + }, + + #[command(about = "Run project")] + Up { + #[arg( + long = "init", + help = "Run any pod initialization commands (for first startup)" + )] + init: bool, + + #[arg( + value_name = "POD_OR_SERVICE", + help = "Pod or service names. Defaults to all." + )] + pod_or_service: Vec, + }, + + #[command(about = "Restart all services associated with this project")] + Restart { + #[arg( + value_name = "POD_OR_SERVICE", + help = "Pod or service names. Defaults to all." + )] + pod_or_service: Vec, + }, + + #[command(about = "Stop all containers associated with this project")] + Stop { + #[arg( + value_name = "POD_OR_SERVICE", + help = "Pod or service names. Defaults to all." + )] + pod_or_service: Vec, + }, + + #[command(about = "Remove the containers associated with a pod or service")] + Rm { + #[arg(short = 'f', long = "force", help = "Remove without confirming first")] + force: bool, + + #[arg( + short = 'v', + help = "Remove anonymous volumes associated with containers" + )] + remove_volumes: bool, + + #[arg( + value_name = "POD_OR_SERVICE", + help = "Pod or service names. Defaults to all." + )] + pod_or_service: Vec, + }, + + #[command( + about = "Run a specific pod as a one-shot task", + trailing_var_arg = true + )] + Run { + #[arg(short = 'd', help = "Run command detached in background")] + detached: bool, + + #[arg( + long = "user", + value_name = "USER", + help = "User as which to run a command" + )] + user: Option, + + #[arg(short = 'T', help = "Do not allocate a TTY when running a command")] + no_allocate_tty: bool, + + #[arg( + long = "entrypoint", + value_name = "ENTRYPOINT", + help = "Override the entrypoint of the service" + )] + entrypoint: Option, + + #[arg(short = 'e', value_names = &["KEY", "VAL"], num_args = 2, value_delimiter = '=', help = "Set an environment variable in the container")] + environment: Vec, + + #[arg( + value_name = "SERVICE", + help = "The name of the service, either as `pod/service`, or as just `service` if unique" + )] + service: String, + + #[arg( + value_name = "COMMAND", + help = "The command to run, with any arguments" + )] + command: Vec, + }, + + #[command( + about = "Run a named script defined in metadata for specified pods or services" + )] + RunScript { + #[arg( + long = "no-deps", + help = "Do not start linked services when running scripts" + )] + no_deps: bool, + + #[arg(value_name = "SCRIPT_NAME", help = "The named script to run")] + script_name: String, + + #[arg( + value_name = "POD_OR_SERVICE", + help = "Pod or service names. Defaults to all." + )] + pod_or_service: Vec, + }, + + #[command( + about = "Run a command inside an existing container", + trailing_var_arg = true + )] + Exec { + #[arg(short = 'd', help = "Run command detached in background")] + detached: bool, + + #[arg( + long = "user", + value_name = "USER", + help = "User as which to run a command" + )] + user: Option, + + #[arg(short = 'T', help = "Do not allocate a TTY when running a command")] + no_allocate_tty: bool, + + #[arg(long = "privileged", help = "Run a command with elevated privileges")] + privileged: bool, + + #[arg( + value_name = "SERVICE", + help = "The name of the service, either as `pod/service`, or as just `service` if unique" + )] + service: String, + + #[arg( + value_name = "COMMAND", + help = "The command to run, with any arguments" + )] + command: Vec, + }, + + #[command(about = "Run an interactive shell inside a running container")] + Shell { + #[arg(short = 'd', help = "Run command detached in background")] + detached: bool, + + #[arg( + long = "user", + value_name = "USER", + help = "User as which to run a command" + )] + user: Option, + + #[arg(short = 'T', help = "Do not allocate a TTY when running a command")] + no_allocate_tty: bool, + + #[arg(long = "privileged", help = "Run a command with elevated privileges")] + privileged: bool, + + #[arg( + value_name = "SERVICE", + help = "The name of the service, either as `pod/service`, or as just `service` if unique" + )] + service: String, + }, + + #[command( + about = "Run the tests associated with a service, if any", + trailing_var_arg = true, + after_help = r#"To enable tests for a service, add a label with the test command. +Assuming your service uses rspec, this might look like: + + myservice: + labels: + io.fdy.cage.test: "rspec" + +Run this test command using: + + cage test myservice + +To run only a subset of your tests, you can also pass a custom test +command: + + cage test myservice rspec spec/my_new_feature_spec.rb +"# + )] + Test { + #[arg( + long = "export-test-output", + help = "Copy container's $WORKDIR/test_output to $PROJECT_DIR/test_output" + )] + export_test_output: bool, + + #[arg( + value_name = "SERVICE", + help = "The name of the service, either as `pod/service`, or as just `service` if unique" + )] + service: String, + + #[arg( + value_name = "COMMAND", + help = "The command to run, with any arguments" + )] + command: Vec, + }, + + #[command(about = "Display logs for a service")] + Logs { + #[arg(short = 'f', help = "Follow log output")] + follow: bool, + + #[arg( + long = "tail", + value_name = "NUMBER", + help = "Number of lines from end of output to display" + )] + number: Option, + + #[arg( + value_name = "POD_OR_SERVICE", + help = "Pod or service names. Defaults to all." + )] + pod_or_service: Vec, + }, + + #[command( + about = "Commands for working with git repositories and local source trees" + )] + Source { + #[command(subcommand)] + command: SourceCommands, + }, + + #[command(about = "Commands for generating new source files")] + Generate { + #[command(subcommand)] + command: GenerateCommands, + }, + + #[command(about = "Export project as flattened *.yml files")] + Export { + #[arg(value_name = "DIR", help = "The name of the directory to create")] + dir: String, + }, +} - /// Extract `exec::Command` from our command-line arguments. - fn to_exec_command(&self) -> Option; +#[derive(Subcommand, Debug)] +enum SourceCommands { + #[command(about = "List all known source tree aliases and URLs")] + Ls, + + #[command( + about = "Clone a git repository using its short alias and mount it into the containers that use it" + )] + Clone { + #[arg( + value_name = "ALIAS", + help = "The short alias of the repo to clone (see `source list`)" + )] + alias: String, + }, + + #[command(about = "Mount a source tree into the containers that use it")] + Mount { + #[arg( + value_name = "ALIASES", + help = "The short aliases of the source trees to operate on (see `source list`)" + )] + aliases: Vec, + + #[arg( + short = 'a', + long = "all", + help = "Operate on all source trees", + conflicts_with = "aliases" + )] + all: bool, + }, + + #[command(about = "Unmount a local source tree from all containers")] + Unmount { + #[arg( + value_name = "ALIASES", + help = "The short aliases of the source trees to operate on (see `source list`)" + )] + aliases: Vec, + + #[arg( + short = 'a', + long = "all", + help = "Operate on all source trees", + conflicts_with = "aliases" + )] + all: bool, + }, +} - /// Extract 'logs' options from our command-line arguments. - fn to_logs_options(&self) -> cage::args::opts::Logs; +#[derive(Subcommand, Debug)] +enum GenerateCommands { + #[command( + about = "Generate shell autocompletion support", + after_help = r#"To set up shell auto-completion for bash: + + cage generate completion bash + source cage.bash-completion + +And set up your ~/.profile or ~/.bash_profile to source this file on +each login. + +To set up shell auto-completion for fish: + + cage generate completion fish + source cage.fish + mkdir -p ~/.config/fish/completions + mv cage.fish ~/.config/fish/completions +"# + )] + Completion { + #[arg( + value_enum, + value_name = "SHELL", + help = "The name of shell for which to generate an autocompletion script" + )] + shell: Shell, + }, + + #[command(about = "Generate config/secrets.yml for local secret storage")] + Secrets, + + #[command(about = "Generate config/vault.yml for fetching secrets from vault")] + Vault, +} - /// Extract 'rm' options from our command-line arguments. - fn to_rm_options(&self) -> cage::args::opts::Rm; +#[derive(Debug, Clone, ValueEnum)] +enum Shell { + Bash, + Fish, } -impl<'a> ArgMatchesExt for clap::ArgMatches<'a> { +impl Cli { fn should_output_project(&self) -> bool { - self.subcommand_name() != Some("export") + !matches!(self.command, Commands::Export { .. }) } fn target_name(&self) -> &str { - self.value_of("target").unwrap_or_else(|| { - if self.subcommand_name() == Some("test") { + self.target.as_deref().unwrap_or({ + if matches!(self.command, Commands::Test { .. }) { "test" } else { "development" } }) } +} - fn to_acts_on(&self, arg_name: &str, include_tasks: bool) -> cage::args::ActOn { - let names: Vec = self - .values_of(arg_name) - .map_or_else(Vec::new, |p| p.collect()) - .iter() - .map(|&p| p.to_string()) - .collect(); - if names.is_empty() { - if include_tasks { - cage::args::ActOn::All - } else { - cage::args::ActOn::AllExceptTasks - } +fn to_acts_on(pod_or_service: &[String], include_tasks: bool) -> cage::args::ActOn { + if pod_or_service.is_empty() { + if include_tasks { + cage::args::ActOn::All } else { - cage::args::ActOn::Named(names) + cage::args::ActOn::AllExceptTasks } + } else { + cage::args::ActOn::Named(pod_or_service.to_vec()) } +} - /// Determine what pods or services we're supposed to act on. - fn to_acts_on_sources(&self, proj: &Project) -> Result { - if self.is_present("ALL") { - Ok(cage::args::ActOnSources::All) - } else if let Some(aliases) = self.values_of("ALIASES") { - let aliases = aliases - .map(|a| -> Result { - if proj.sources().find_by_alias(a).is_none() { - Err(ErrorKind::UnknownSource(a.to_owned()).into()) - } else { - Ok(a.to_owned()) - } - }) - .collect::>>()?; - Ok(cage::args::ActOnSources::Named(aliases)) - } else { - panic!("clap source always require --all or a list of sources"); - } +fn to_acts_on_sources( + aliases: &[String], + all: bool, + proj: &Project, +) -> Result { + if all { + Ok(cage::args::ActOnSources::All) + } else if !aliases.is_empty() { + let validated_aliases = aliases + .iter() + .map(|a| -> Result { + if proj.sources().find_by_alias(a).is_none() { + Err(Error::UnknownSource(a.to_owned()).into()) + } else { + Ok(a.to_owned()) + } + }) + .collect::>>()?; + Ok(cage::args::ActOnSources::Named(validated_aliases)) + } else { + panic!("clap source always require --all or a list of sources"); } +} - fn to_process_options(&self) -> cage::args::opts::Process { - let mut opts = cage::args::opts::Process::default(); - opts.detached = self.is_present("detached"); - opts.user = self.value_of("user").map(|v| v.to_owned()); - opts.allocate_tty = !self.is_present("no-allocate-tty"); - opts - } +fn to_process_options( + detached: bool, + user: &Option, + no_allocate_tty: bool, +) -> cage::args::opts::Process { + let mut opts = cage::args::opts::Process::default(); + opts.detached = detached; + opts.user = user.clone(); + opts.allocate_tty = !no_allocate_tty; + opts +} - fn to_exec_options(&self) -> cage::args::opts::Exec { - let mut opts = cage::args::opts::Exec::default(); - opts.process = self.to_process_options(); - opts.privileged = self.is_present("privileged"); - opts - } +fn to_exec_options( + detached: bool, + user: &Option, + no_allocate_tty: bool, + privileged: bool, +) -> cage::args::opts::Exec { + let mut opts = cage::args::opts::Exec::default(); + opts.process = to_process_options(detached, user, no_allocate_tty); + opts.privileged = privileged; + opts +} - fn to_run_options(&self) -> cage::args::opts::Run { - let mut opts = cage::args::opts::Run::default(); - opts.process = self.to_process_options(); - opts.entrypoint = self.value_of("entrypoint").map(|v| v.to_owned()); - if let Some(environment) = self.values_of("environment") { - let environment: Vec<&str> = environment.collect(); - for env_val in environment.chunks(2) { - if env_val.len() != 2 { - // Clap should prevent this. - panic!("Environment binding '{}' has no value", env_val[0]); - } - opts.environment - .insert(env_val[0].to_owned(), env_val[1].to_owned()); - } +fn to_run_options( + detached: bool, + user: &Option, + no_allocate_tty: bool, + entrypoint: &Option, + environment: &[String], + no_deps: bool, +) -> cage::args::opts::Run { + let mut opts = cage::args::opts::Run::default(); + opts.process = to_process_options(detached, user, no_allocate_tty); + opts.entrypoint = entrypoint.clone(); + + let mut env_map = BTreeMap::new(); + for chunk in environment.chunks(2) { + if chunk.len() == 2 { + env_map.insert(chunk[0].to_owned(), chunk[1].to_owned()); } - opts.no_deps = self.is_present("no-deps"); - opts } + opts.environment = env_map; + opts.no_deps = no_deps; + opts +} - /// Extract `test` options from our command-line arguments. - fn to_test_options(&self) -> cage::args::opts::Test { - let mut opts = cage::args::opts::Test::default(); - opts.export_test_output = self.is_present("export-test-output"); - opts - } +fn to_test_options(export_test_output: bool) -> cage::args::opts::Test { + let mut opts = cage::args::opts::Test::default(); + opts.export_test_output = export_test_output; + opts +} - fn to_logs_options(&self) -> cage::args::opts::Logs { - let mut opts = cage::args::opts::Logs::default(); - opts.follow = self.is_present("follow"); - opts.number = self.value_of("number").map(|v| v.to_owned()); - opts - } +fn to_logs_options(follow: bool, number: &Option) -> cage::args::opts::Logs { + let mut opts = cage::args::opts::Logs::default(); + opts.follow = follow; + opts.number = number.clone(); + opts +} - fn to_rm_options(&self) -> cage::args::opts::Rm { - let mut opts = cage::args::opts::Rm::default(); - opts.force = self.is_present("force"); - opts.remove_volumes = self.is_present("remove-volumes"); - opts - } +fn to_rm_options(force: bool, remove_volumes: bool) -> cage::args::opts::Rm { + let mut opts = cage::args::opts::Rm::default(); + opts.force = force; + opts.remove_volumes = remove_volumes; + opts +} - fn to_exec_command(&self) -> Option { - if self.is_present("COMMAND") { - let values: Vec<&str> = self.values_of("COMMAND").unwrap().collect(); - assert!(!values.is_empty(), "too few values from CLI parser"); - Some(cage::args::Command::new(values[0]).with_args(&values[1..])) - } else { - None - } +fn to_exec_command(command: &[String]) -> Option { + if command.is_empty() { + None + } else { + Some(cage::args::Command::new(&command[0]).with_args(&command[1..])) } } @@ -207,25 +604,15 @@ fn warn_if_pods_are_enabled_but_not_running(project: &cage::Project) -> Result<( /// The function which does the real work. Unlike `main`, we have a return /// type of `Result` and may therefore use `?` to handle errors. -fn run(matches: &clap::ArgMatches<'_>) -> Result<()> { - // We know that we always have a subcommand because our `cli.yml` - // requires this and `clap` is supposed to enforce it. - let sc_name = matches.subcommand_name().unwrap(); - let sc_matches: &clap::ArgMatches<'_> = - matches.subcommand_matches(sc_name).unwrap(); - - // Handle any subcommands that we can handle without a project - // directory. - match sc_name { - "sysinfo" => { +fn run(cli: &Cli) -> Result<()> { + // Handle any subcommands that we can handle without a project directory. + match &cli.command { + Commands::Sysinfo => { all_versions()?; return Ok(()); } - "new" => { - cage::Project::generate_new( - &env::current_dir()?, - sc_matches.value_of("NAME").unwrap(), - )?; + Commands::New { name } => { + cage::Project::generate_new(&env::current_dir()?, name)?; return Ok(()); } _ => {} @@ -233,106 +620,170 @@ fn run(matches: &clap::ArgMatches<'_>) -> Result<()> { // Handle our standard arguments that apply to all subcommands. let mut proj = cage::Project::from_current_dir()?; - if let Some(project_name) = matches.value_of("project-name") { + if let Some(project_name) = &cli.project_name { proj.set_name(project_name); } - if let Some(default_tags_path) = matches.value_of("default-tags") { + if let Some(default_tags_path) = &cli.default_tags { let f = fs::File::open(default_tags_path)?; let reader = io::BufReader::new(f); proj.set_default_tags(cage::DefaultTags::read(reader)?); } - proj.set_current_target_name(matches.target_name())?; - - // Output our project's `*.yml` files for `docker-compose` if we'll - // need it. - if matches.should_output_project() { - proj.output(sc_name)?; + proj.set_current_target_name(cli.target_name())?; + + // Output our project's `*.yml` files for `docker-compose` if we'll need it. + let subcommand_name = match &cli.command { + Commands::Sysinfo => "sysinfo", + Commands::New { .. } => "new", + Commands::Status { .. } => "status", + Commands::Build { .. } => "build", + Commands::Pull { .. } => "pull", + Commands::Up { .. } => "up", + Commands::Restart { .. } => "restart", + Commands::Stop { .. } => "stop", + Commands::Rm { .. } => "rm", + Commands::Run { .. } => "run", + Commands::RunScript { .. } => "run-script", + Commands::Exec { .. } => "exec", + Commands::Shell { .. } => "shell", + Commands::Test { .. } => "test", + Commands::Source { .. } => "source", + Commands::Generate { .. } => "generate", + Commands::Logs { .. } => "logs", + Commands::Export { .. } => "export", + }; + + if cli.should_output_project() { + proj.output(subcommand_name)?; } // Handle our subcommands that require a `Project`. let runner = OsCommandRunner::new(); - match sc_name { - "status" => { - let acts_on = sc_matches.to_acts_on("POD_OR_SERVICE", true); + match &cli.command { + Commands::Status { pod_or_service } => { + let acts_on = to_acts_on(pod_or_service, true); proj.status(&runner, &acts_on)?; } - "pull" => { - let acts_on = sc_matches.to_acts_on("POD_OR_SERVICE", true); + Commands::Pull { + quiet, + pod_or_service, + } => { + let acts_on = to_acts_on(pod_or_service, true); let mut opts = cage::args::opts::Pull::default(); - opts.quiet = sc_matches.is_present("quiet"); + opts.quiet = *quiet; proj.pull(&runner, &acts_on, &opts)?; } - "build" => { - let acts_on = sc_matches.to_acts_on("POD_OR_SERVICE", true); + Commands::Build { pod_or_service } => { + let acts_on = to_acts_on(pod_or_service, true); let opts = cage::args::opts::Empty; proj.compose(&runner, "build", &acts_on, &opts)?; } - "up" => { - let acts_on = sc_matches.to_acts_on("POD_OR_SERVICE", false); - let opts = cage::args::opts::Up::new(sc_matches.is_present("init")); + Commands::Up { + init, + pod_or_service, + } => { + let acts_on = to_acts_on(pod_or_service, false); + let opts = cage::args::opts::Up::new(*init); proj.up(&runner, &acts_on, &opts)?; } - "restart" => { - let acts_on = sc_matches.to_acts_on("POD_OR_SERVICE", false); + Commands::Restart { pod_or_service } => { + let acts_on = to_acts_on(pod_or_service, false); let opts = cage::args::opts::Empty; proj.compose(&runner, "restart", &acts_on, &opts)?; } - "stop" => { - let acts_on = sc_matches.to_acts_on("POD_OR_SERVICE", false); + Commands::Stop { pod_or_service } => { + let acts_on = to_acts_on(pod_or_service, false); let opts = cage::args::opts::Empty; proj.compose(&runner, "stop", &acts_on, &opts)?; } - "rm" => { - let acts_on = sc_matches.to_acts_on("POD_OR_SERVICE", true); - let opts = sc_matches.to_rm_options(); + Commands::Rm { + force, + remove_volumes, + pod_or_service, + } => { + let acts_on = to_acts_on(pod_or_service, true); + let opts = to_rm_options(*force, *remove_volumes); proj.compose(&runner, "rm", &acts_on, &opts)?; } - "run" => { + Commands::Run { + detached, + user, + no_allocate_tty, + entrypoint, + environment, + service, + command, + } => { warn_if_pods_are_enabled_but_not_running(&proj)?; - let opts = sc_matches.to_run_options(); - let cmd = sc_matches.to_exec_command(); - let service = sc_matches.value_of("SERVICE").unwrap(); + let opts = to_run_options( + *detached, + user, + *no_allocate_tty, + entrypoint, + environment, + false, + ); + let cmd = to_exec_command(command); proj.run(&runner, service, cmd.as_ref(), &opts)?; } - "run-script" => { + Commands::RunScript { + no_deps, + script_name, + pod_or_service, + } => { warn_if_pods_are_enabled_but_not_running(&proj)?; - let opts = sc_matches.to_run_options(); - let script_name = sc_matches.value_of("SCRIPT_NAME").unwrap(); - let acts_on = sc_matches.to_acts_on("POD_OR_SERVICE", true); + let opts = to_run_options(false, &None, false, &None, &[], *no_deps); + let acts_on = to_acts_on(pod_or_service, true); proj.run_script(&runner, &acts_on, script_name.as_ref(), &opts)?; } - "exec" => { + Commands::Exec { + detached, + user, + no_allocate_tty, + privileged, + service, + command, + } => { warn_if_pods_are_enabled_but_not_running(&proj)?; - let service = sc_matches.value_of("SERVICE").unwrap(); - let opts = sc_matches.to_exec_options(); - let cmd = sc_matches.to_exec_command().unwrap(); + let opts = to_exec_options(*detached, user, *no_allocate_tty, *privileged); + let cmd = to_exec_command(command).unwrap(); proj.exec(&runner, service, &cmd, &opts)?; } - "shell" => { + Commands::Shell { + detached, + user, + no_allocate_tty, + privileged, + service, + } => { warn_if_pods_are_enabled_but_not_running(&proj)?; - let service = sc_matches.value_of("SERVICE").unwrap(); - let opts = sc_matches.to_exec_options(); + let opts = to_exec_options(*detached, user, *no_allocate_tty, *privileged); proj.shell(&runner, service, &opts)?; } - "test" => { + Commands::Test { + export_test_output, + service, + command, + } => { warn_if_pods_are_enabled_but_not_running(&proj)?; - let service = sc_matches.value_of("SERVICE").unwrap(); - let opts = sc_matches.to_test_options(); - let cmd = sc_matches.to_exec_command(); + let opts = to_test_options(*export_test_output); + let cmd = to_exec_command(command); proj.test(&runner, service, cmd.as_ref(), &opts)?; } - "source" => run_source(&runner, &mut proj, sc_matches)?, - "generate" => run_generate(&runner, &proj, sc_matches)?, - "logs" => { - let acts_on = sc_matches.to_acts_on("POD_OR_SERVICE", true); - let opts = sc_matches.to_logs_options(); + Commands::Source { command } => run_source(&runner, &mut proj, command)?, + Commands::Generate { command } => run_generate(&runner, &proj, command)?, + Commands::Logs { + follow, + number, + pod_or_service, + } => { + let acts_on = to_acts_on(pod_or_service, true); + let opts = to_logs_options(*follow, number); proj.logs(&runner, &acts_on, &opts)?; } - "export" => { - let dir = sc_matches.value_of("DIR").unwrap(); + Commands::Export { dir } => { proj.export(Path::new(dir))?; } - unknown => unreachable!("Unexpected subcommand '{}'", unknown), + _ => unreachable!(), } Ok(()) @@ -342,42 +793,41 @@ fn run(matches: &clap::ArgMatches<'_>) -> Result<()> { fn run_source( runner: &R, proj: &mut cage::Project, - matches: &clap::ArgMatches<'_>, + command: &SourceCommands, ) -> Result<()> where R: CommandRunner, { - // We know that we always have a subcommand because our `cli.yml` - // requires this and `clap` is supposed to enforce it. - let sc_name = matches.subcommand_name().unwrap(); - let sc_matches: &clap::ArgMatches<'_> = - matches.subcommand_matches(sc_name).unwrap(); + let subcommand_name = match command { + SourceCommands::Ls => "ls", + SourceCommands::Clone { .. } => "clone", + SourceCommands::Mount { .. } => "mount", + SourceCommands::Unmount { .. } => "unmount", + }; // Dispatch our subcommand. let mut re_output = true; - match sc_name { - "ls" => { + match command { + SourceCommands::Ls => { re_output = false; proj.source_list(runner)?; } - "clone" => { - let alias = sc_matches.value_of("ALIAS").unwrap(); + SourceCommands::Clone { alias } => { proj.source_clone(runner, alias)?; } - "mount" => { - let act_on_sources = sc_matches.to_acts_on_sources(proj)?; + SourceCommands::Mount { aliases, all } => { + let act_on_sources = to_acts_on_sources(aliases, *all, proj)?; proj.source_set_mounted(runner, act_on_sources, true)?; } - "unmount" => { - let act_on_sources = sc_matches.to_acts_on_sources(proj)?; + SourceCommands::Unmount { aliases, all } => { + let act_on_sources = to_acts_on_sources(aliases, *all, proj)?; proj.source_set_mounted(runner, act_on_sources, false)?; } - unknown => unreachable!("Unexpected subcommand '{}'", unknown), } // Regenerate our output if it might have changed. if re_output { - proj.output(sc_name)?; + proj.output(subcommand_name)?; } Ok(()) @@ -387,29 +837,28 @@ where fn run_generate( _runner: &R, proj: &cage::Project, - matches: &clap::ArgMatches<'_>, + command: &GenerateCommands, ) -> Result<()> where R: CommandRunner, { - // We know that we always have a subcommand because our `cli.yml` - // requires this and `clap` is supposed to enforce it. - let sc_name = matches.subcommand_name().unwrap(); - let sc_matches: &clap::ArgMatches<'_> = - matches.subcommand_matches(sc_name).unwrap(); - - match sc_name { - // TODO LOW: Allow running this without a project? - "completion" => { - let shell = match sc_matches.value_of("SHELL").unwrap() { - "bash" => clap::Shell::Bash, - "fish" => clap::Shell::Fish, - unknown => unreachable!("Unknown shell '{}'", unknown), - }; - let cli_yaml = load_yaml!("cli.yml"); - cli(cli_yaml).gen_completions("cage", shell, proj.root_dir()); + match command { + GenerateCommands::Completion { shell } => { + use clap::CommandFactory; + use clap_complete::{generate, shells}; + + let mut cmd = Cli::command(); + match shell { + Shell::Bash => { + generate(shells::Bash, &mut cmd, "cage", &mut io::stdout()) + } + Shell::Fish => { + generate(shells::Fish, &mut cmd, "cage", &mut io::stdout()) + } + } } - other => proj.generate(other)?, + GenerateCommands::Secrets => proj.generate("secrets")?, + GenerateCommands::Vault => proj.generate("vault")?, } Ok(()) } @@ -443,13 +892,18 @@ fn log_level_label(level: log::Level) -> colored::ColoredString { /// Our main entry point. fn main() { - openssl_probe::init_ssl_cert_env_vars(); + unsafe { + openssl_probe::init_openssl_env_vars(); + } // Initialize logging with some custom options, mostly so we can see // our own warnings. let mut builder = env_logger::Builder::new(); - builder.filter(Some("compose_yml"), log::LevelFilter::Warn); - builder.filter(Some("compose_yml::v2::validate"), log::LevelFilter::Error); + builder.filter(Some("faraday_compose_yml"), log::LevelFilter::Warn); + builder.filter( + Some("faraday_compose_yml::v2::validate"), + log::LevelFilter::Error, + ); builder.filter(Some("cage"), log::LevelFilter::Warn); builder.format( |f: &mut env_logger::fmt::Formatter, record: &log::Record<'_>| { @@ -472,23 +926,16 @@ fn main() { builder.init(); // Parse our command-line arguments. - let cli_yaml = load_yaml!("cli.yml"); - let matches: clap::ArgMatches<'_> = cli(cli_yaml).get_matches(); - debug!("Arguments: {:?}", &matches); + let cli = Cli::parse(); + debug!("Arguments: {:?}", &cli); // Defer all our real work to `run`, and handle any errors. This is a // standard Rust pattern to make error-handling in `main` nicer. - if let Err(ref err) = run(&matches) { + if let Err(ref err) = run(&cli) { // We use `unwrap` here to turn I/O errors into application panics. // If we can't print a message to stderr without an I/O error, // the situation is hopeless. - eprint!("Error: "); - for e in err.iter() { - eprintln!("{}", e); - } - if let Some(backtrace) = err.backtrace() { - eprintln!("{:?}", backtrace); - } + eprintln!("Error: {:#}", err); process::exit(1); } } diff --git a/src/plugins/mod.rs b/src/plugins/mod.rs index 1f7f7730..a87d93b4 100644 --- a/src/plugins/mod.rs +++ b/src/plugins/mod.rs @@ -1,6 +1,6 @@ //! Plugin support. -use compose_yml::v2 as dc; +use faraday_compose_yml::v2 as dc; use std::fmt; use std::io; use std::marker::PhantomData; @@ -155,7 +155,8 @@ impl Manager { where T: PluginNew + 'static, { - T::new(proj).chain_err(|| ErrorKind::PluginFailed(T::plugin_name().to_owned())) + T::new(proj) + .map_err(|e| e.context(Error::PluginFailed(T::plugin_name().to_owned()))) } /// Register a generator with this manager. @@ -181,9 +182,9 @@ impl Manager { } /// A plugin was missing, so build an appropriate error message. - fn missing_plugin(&self, name: &str) -> ErrorKind { + fn missing_plugin(&self, name: &str) -> anyhow::Error { if name == "vault" { - ErrorKind::FeatureDisabled + Error::FeatureDisabled.into() } else { unreachable!("Cannot find a generator named {}", name) } @@ -214,9 +215,9 @@ impl Manager { ) -> Result<()> { for plugin in &self.transforms { trace!("transforming '{}' with {}", ctx.pod.name(), plugin.name()); - plugin - .transform(op, ctx, file) - .chain_err(|| ErrorKind::PluginFailed(plugin.name().to_owned()))?; + plugin.transform(op, ctx, file).map_err(|e| { + e.context(Error::PluginFailed(plugin.name().to_owned())) + })?; } Ok(()) } diff --git a/src/plugins/transform/abs_path.rs b/src/plugins/transform/abs_path.rs index 19659688..09508b33 100644 --- a/src/plugins/transform/abs_path.rs +++ b/src/plugins/transform/abs_path.rs @@ -1,6 +1,6 @@ //! Plugin which converts all paths in a `dc::File` to absolute. -use compose_yml::v2 as dc; +use faraday_compose_yml::v2 as dc; use std::marker::PhantomData; use crate::errors::*; diff --git a/src/plugins/transform/default_tags.rs b/src/plugins/transform/default_tags.rs index 065c81a5..f85c1911 100644 --- a/src/plugins/transform/default_tags.rs +++ b/src/plugins/transform/default_tags.rs @@ -1,6 +1,6 @@ //! Plugin which applies `DefaultTags` to `dc::File`. -use compose_yml::v2 as dc; +use faraday_compose_yml::v2 as dc; use std::marker::PhantomData; use crate::errors::*; diff --git a/src/plugins/transform/host_dns.rs b/src/plugins/transform/host_dns.rs index f29a2082..6bd414f1 100644 --- a/src/plugins/transform/host_dns.rs +++ b/src/plugins/transform/host_dns.rs @@ -3,7 +3,7 @@ //! This allows containers to talk to the host. It's set up automatically on //! MacOS, but not yet on Linux. -use compose_yml::v2 as dc; +use faraday_compose_yml::v2 as dc; use std::{ marker::PhantomData, net::IpAddr, @@ -70,9 +70,9 @@ impl PluginTransform for Plugin { return Ok(()); } }; - let addr = addr - .parse::() - .chain_err(|| err!("invalid IP address {:?}", addr))?; + let addr = addr.parse::().map_err(|e| { + anyhow::Error::new(e).context(format!("invalid IP address {:?}", addr)) + })?; trace!("mapping host.docker.internal to {}", addr); // Add an extra host to each service. @@ -104,14 +104,19 @@ impl InterfaceInfo { // TODO: Should we use our `command_runner` for this so that we can mock // it during tests? let output = Command::new("ip") - .args(&["-j", "address", "show", ifname]) + .args(["-j", "address", "show", ifname]) .stderr(Stdio::inherit()) .output() - .chain_err(|| "error running `ip address show`")?; + .map_err(|e| { + anyhow::Error::new(e).context("error running `ip address show`") + })?; if output.status.success() { let data = output.stdout; let interfaces = serde_json::from_slice::>(&data) - .chain_err(|| "error parsing `ip address show` output")?; + .map_err(|e| { + anyhow::Error::new(e) + .context("error parsing `ip address show` output") + })?; for i in &interfaces { if let Some(found_ifname) = &i.ifname { if found_ifname == ifname { diff --git a/src/plugins/transform/labels.rs b/src/plugins/transform/labels.rs index e0b70525..24f20246 100644 --- a/src/plugins/transform/labels.rs +++ b/src/plugins/transform/labels.rs @@ -1,6 +1,6 @@ //! Plugin which updates the `labels` in a `dc::File`. -use compose_yml::v2 as dc; +use faraday_compose_yml::v2 as dc; use std::marker::PhantomData; use crate::errors::*; diff --git a/src/plugins/transform/remove_build.rs b/src/plugins/transform/remove_build.rs index 4d08e613..cd93c176 100644 --- a/src/plugins/transform/remove_build.rs +++ b/src/plugins/transform/remove_build.rs @@ -1,6 +1,6 @@ //! Plugin which removes the `build` field in a in a `dc::File`. -use compose_yml::v2 as dc; +use faraday_compose_yml::v2 as dc; use std::marker::PhantomData; use crate::errors::*; diff --git a/src/plugins/transform/secrets.rs b/src/plugins/transform/secrets.rs index 28c7c2e5..3e296364 100644 --- a/src/plugins/transform/secrets.rs +++ b/src/plugins/transform/secrets.rs @@ -1,7 +1,7 @@ //! Plugin which loads secrets from `config/secrets.yml` and adds them to a //! project. -use compose_yml::v2 as dc; +use faraday_compose_yml::v2 as dc; use std::collections::BTreeMap; #[cfg(test)] use std::path::Path; @@ -161,17 +161,17 @@ impl PluginTransform for Plugin { } }; - for (name, mut service) in &mut file.services { + for (name, service) in &mut file.services { service .environment .append(&mut config.common.to_compose_env()); - append_service(&mut service, &config.pods, name); + append_service(service, &config.pods, name); let target_name = ctx.project.current_target().name(); if let Some(target) = config.targets.get(target_name) { service .environment .append(&mut target.common.to_compose_env()); - append_service(&mut service, &target.pods, name); + append_service(service, &target.pods, name); } } Ok(()) diff --git a/src/plugins/transform/sources.rs b/src/plugins/transform/sources.rs index af0f37ee..a727b391 100644 --- a/src/plugins/transform/sources.rs +++ b/src/plugins/transform/sources.rs @@ -2,7 +2,7 @@ //! repositories, and which handles mounting local source trees into //! containers. -use compose_yml::v2 as dc; +use faraday_compose_yml::v2 as dc; use std::marker::PhantomData; #[cfg(test)] use std::path::Path; diff --git a/src/plugins/transform/vault.rs b/src/plugins/transform/vault.rs index c488cb0b..dbf8db62 100644 --- a/src/plugins/transform/vault.rs +++ b/src/plugins/transform/vault.rs @@ -1,6 +1,6 @@ //! Plugin which issues vault tokens to services. -use compose_yml::v2 as dc; +use faraday_compose_yml::v2 as dc; use std::{ collections::{btree_map::Entry, BTreeMap, BTreeSet}, env, @@ -175,11 +175,14 @@ fn load_vault_token_from_file() -> Result { let path = dirs::home_dir() .ok_or_else(|| err("You do not appear to have a home directory"))? .join(".vault-token"); - let mkerr = || ErrorKind::CouldNotReadFile(path.clone()); - let f = fs::File::open(&path).chain_err(&mkerr)?; + let f = fs::File::open(&path).map_err(|e| { + anyhow::Error::new(e).context(Error::CouldNotReadFile(path.clone())) + })?; let mut reader = io::BufReader::new(f); let mut result = String::new(); - reader.read_to_string(&mut result).chain_err(&mkerr)?; + reader.read_to_string(&mut result).map_err(|e| { + anyhow::Error::new(e).context(Error::CouldNotReadFile(path.clone())) + })?; Ok(result.trim().to_owned()) } @@ -303,21 +306,22 @@ impl GenerateToken for Vault { policies: &BTreeSet, ttl: Duration, ) -> Result { - let mkerr = || ErrorKind::VaultError(self.addr.clone()); - // We can't store `client` in `self`, because it has some obnoxious // lifetime parameters. So we'll just recreate it. This is // probably not the worst idea, because it uses `hyper` for HTTP, // and `hyper` HTTP connections used to have expiration issues that // were tricky for clients to deal with correctly. - let client = - vault::Client::new(&self.addr[..], &self.token).chain_err(&mkerr)?; + let client = vault::Client::new(&self.addr[..], &self.token).map_err(|e| { + anyhow::anyhow!("{}: {}", Error::VaultError(self.addr.clone()), e) + })?; let opts = vault::client::TokenOptions::default() .display_name(display_name) .renewable(true) .ttl(VaultDuration(ttl)) .policies(policies.clone()); - let auth = client.create_token(&opts).chain_err(&mkerr)?; + let auth = client.create_token(&opts).map_err(|e| { + anyhow::anyhow!("{}: {}", Error::VaultError(self.addr.clone()), e) + })?; let lease_duration = auth .lease_duration .map_or_else(|| Duration::from_secs(30 * 24 * 60 * 60), |d| d.0); @@ -353,7 +357,7 @@ impl CachedTokens { target: String, pod: String, service: String, - ) -> Entry { + ) -> Entry<'_, String, TokenInfo> { self.targets .entry(target) .or_default() @@ -418,7 +422,9 @@ impl<'gen> TokenCache<'gen> { ) -> Result<&'cache TokenInfo> { // Helper functions used in several places below. let display_name = || format!("{}_{}_{}_{}", project, target, pod, service); - let mkerr = || format!("could not generate token for '{}'", service); + let mkerr = |e: anyhow::Error| { + e.context(format!("could not generate token for '{}'", service)) + }; // Look up what we have in the cache and decide what to do. let entry = @@ -435,19 +441,19 @@ impl<'gen> TokenCache<'gen> { let info = self .generator .generate_token(&display_name(), policies, ttl) - .chain_err(mkerr)?; + .map_err(mkerr)?; Ok(vacancy.insert(info)) } Entry::Occupied(occupied) => { trace!("token cache hit for {}", service); let cached = occupied.into_mut(); - if cached.should_renew(&policies, ttl) { + if cached.should_renew(policies, ttl) { trace!("token cache needs new token for {}", service); // We'll need a new token. *cached = self .generator .generate_token(&display_name(), policies, ttl) - .chain_err(mkerr)?; + .map_err(mkerr)?; } Ok(cached) } @@ -551,7 +557,7 @@ impl PluginTransform for Plugin { // Set up our token cache. let mut cache = - TokenCache::load_or_create(&ctx.project, &ctx.pod, generator.as_ref())?; + TokenCache::load_or_create(ctx.project, ctx.pod, generator.as_ref())?; // Apply to each service. for (name, service) in &mut file.services { @@ -594,7 +600,7 @@ impl PluginTransform for Plugin { // Interpolate the variables found in our policy patterns. let mut policies = BTreeSet::new(); - for result in raw_policies.iter().map(|p| interpolated(p)) { + for result in raw_policies.iter().map(&interpolated) { // We'd like to use std::result::fold here but it's unstable. policies.insert(result?); } diff --git a/src/pod.rs b/src/pod.rs index 064c7b93..915d04aa 100644 --- a/src/pod.rs +++ b/src/pod.rs @@ -1,7 +1,7 @@ //! A single pod in a project. -use compose_yml::v2 as dc; -use compose_yml::v2::MergeOverride; +use faraday_compose_yml::v2 as dc; +use faraday_compose_yml::v2::MergeOverride; use std::collections::btree_map; use std::collections::{BTreeMap, BTreeSet}; use std::ffi::OsString; @@ -85,10 +85,10 @@ impl Config { if let Some(service_config) = self.services.get(service_name) { service_config.run_script( runner, - &project, - &service_name, - &script_name, - &opts, + project, + service_name, + script_name, + opts, )?; } Ok(()) @@ -118,7 +118,7 @@ impl ServiceConfig { CR: CommandRunner, { if let Some(script) = self.scripts.get(script_name) { - script.run(runner, &project, service_name, &opts)?; + script.run(runner, project, service_name, opts)?; } Ok(()) } @@ -141,14 +141,16 @@ impl Script { { for cmd in &self.0 { if cmd.is_empty() { - return Err("all items in script must have at least one value".into()); + return Err(anyhow::anyhow!( + "all items in script must have at least one value" + )); } let cmd = if cmd.len() >= 2 { Some(args::Command::new(&cmd[0]).with_args(&cmd[1..])) } else { None }; - project.run(runner, service_name, cmd.as_ref(), &opts)?; + project.run(runner, service_name, cmd.as_ref(), opts)?; } Ok(()) } @@ -186,10 +188,9 @@ impl FileInfo { rel_path: rel_path.to_owned(), file: if path.exists() { debug!("Parsing {}", path.display()); - dc::File::read_from_path(&path).chain_err(|| { - // Make sure we tie parse errors to a specific file, for - // the sake of sanity. - ErrorKind::CouldNotReadFile(path.clone()) + dc::File::read_from_path(&path).map_err(|e| { + anyhow::Error::new(e) + .context(Error::CouldNotReadFile(path.clone())) })? } else { Default::default() @@ -213,20 +214,17 @@ impl FileInfo { let introduced: Vec = ours.difference(service_names).cloned().collect(); if !introduced.is_empty() { - return Err(ErrorKind::ServicesAddedInTarget( - base_file.to_owned(), - self.rel_path.clone(), - introduced, - ) + return Err(Error::ServicesAddedInTarget { + base: base_file.to_owned(), + target: self.rel_path.clone(), + names: introduced, + } .into()); } // Add any missing services. for name in service_names { - self.file - .services - .entry(name.to_owned()) - .or_insert_with(Default::default); + self.file.services.entry(name.to_owned()).or_default(); } Ok(()) } @@ -282,7 +280,7 @@ impl Pod { let name = name.into(); // Load our `*.metadata.yml` file, if any. - let config_path = base_dir.join(&format!("{}.metadata.yml", &name)); + let config_path = base_dir.join(format!("{}.metadata.yml", &name)); let config: Config = if config_path.exists() { load_yaml(&config_path)? } else { @@ -409,7 +407,7 @@ impl Pod { /// Like `service`, but returns an error if the service can't be found. pub fn service_or_err(&self, target: &Target, name: &str) -> Result { self.service(target, name)? - .ok_or_else(|| ErrorKind::UnknownService(name.to_owned()).into()) + .ok_or_else(|| Error::UnknownService(name.to_owned()).into()) } /// Command-line `-p` and `-f` arguments that we'll pass to @@ -441,7 +439,7 @@ impl Pod { CR: CommandRunner, { self.config - .run_script(runner, &project, &service_name, &script_name, &opts) + .run_script(runner, project, service_name, script_name, opts) } } diff --git a/src/project.rs b/src/project.rs index 84c88de7..b7c2bb93 100644 --- a/src/project.rs +++ b/src/project.rs @@ -1,7 +1,7 @@ //! A cage project. #[cfg(test)] -use compose_yml::v2 as dc; +use faraday_compose_yml::v2 as dc; use serde::ser::SerializeMap; use serde::{Serialize, Serializer}; use std::env; @@ -58,13 +58,18 @@ impl ProjectConfig { /// Load a config file from the specified path. pub fn new(path: &Path) -> Result { if path.exists() { - let mkerr = || ErrorKind::CouldNotReadFile(path.to_owned()); - let f = fs::File::open(path).chain_err(&mkerr)?; + let f = fs::File::open(path).map_err(|e| { + anyhow::Error::new(e).context(Error::CouldNotReadFile(path.to_owned())) + })?; let mut reader = io::BufReader::new(f); let mut yaml = String::new(); - reader.read_to_string(&mut yaml).chain_err(&mkerr)?; - Self::check_config_version(&path, &yaml)?; - serde_yaml::from_str(&yaml).chain_err(&mkerr) + reader.read_to_string(&mut yaml).map_err(|e| { + anyhow::Error::new(e).context(Error::CouldNotReadFile(path.to_owned())) + })?; + Self::check_config_version(path, &yaml)?; + serde_yaml::from_str(&yaml).map_err(|e| { + anyhow::Error::new(e).context(Error::CouldNotReadFile(path.to_owned())) + }) } else { warn!("No {} file, using default values", path.display()); Ok(Default::default()) @@ -84,11 +89,12 @@ impl ProjectConfig { cage_version: Option, } - let config: VersionOnly = serde_yaml::from_str(config_yml) - .chain_err(|| ErrorKind::CouldNotReadFile(path.to_owned()))?; + let config: VersionOnly = serde_yaml::from_str(config_yml).map_err(|e| { + anyhow::Error::new(e).context(Error::CouldNotReadFile(path.to_owned())) + })?; if let Some(ref req) = config.cage_version { - if !req.matches(&version()) { - return Err(ErrorKind::MismatchedVersion(req.to_owned()).into()); + if !req.matches(version()) { + return Err(Error::MismatchedVersion(req.to_owned()).into()); } } else { warn!( @@ -139,10 +145,8 @@ fn check_config_version() { let yaml = "---\ncage_version: \"0.0.1\"\nunknown_field: true"; let res = ProjectConfig::check_config_version(&p, yaml); assert!(res.is_err()); - match *res.unwrap_err().kind() { - ErrorKind::MismatchedVersion(_) => {} - ref e => panic!("Unexpected error type {}", e), - } + let err_msg = format!("{}", res.unwrap_err()); + assert!(err_msg.contains("cage_version")); } /// Represents either a `Pod` object or a `Service` object. @@ -204,7 +208,7 @@ pub struct Project { hooks: HookManager, /// The main configuration for this project. - config: ProjectConfig, + _config: ProjectConfig, /// Docker image tags to use for images that don't have them. /// Typically used to lock down versions supplied by a CI system. @@ -226,7 +230,7 @@ impl Project { let current_target = targets .iter() .find(|target| target.name() == "development") - .ok_or_else(|| ErrorKind::UnknownTarget("development".into()))? + .ok_or_else(|| Error::UnknownTarget("development".into()))? .to_owned(); let pods = Project::find_pods(root_dir, &targets)?; let service_locations = ServiceLocations::new(&pods); @@ -251,7 +255,7 @@ impl Project { current_target, sources, hooks: HookManager::new(root_dir)?, - config, + _config: config, default_tags: None, plugins: None, }; @@ -418,7 +422,7 @@ impl Project { /// Look up the named service. Returns the pod containing the service /// and the name of the service within that pod. - pub fn service<'a>(&self, name: &'a str) -> Option<(&Pod, &str)> { + pub fn service(&self, name: &str) -> Option<(&Pod, &str)> { if let Some((pod_name, service_name)) = self.service_locations.find(name) { let pod = self.pod(pod_name).expect("pod should exist"); Some((pod, service_name)) @@ -428,17 +432,14 @@ impl Project { } /// Like `service`, but returns an error if the service is unknown. - pub fn service_or_err<'a>(&self, name: &'a str) -> Result<(&Pod, &str)> { + pub fn service_or_err(&self, name: &str) -> Result<(&Pod, &str)> { self.service(name) - .ok_or_else(|| ErrorKind::UnknownService(name.to_owned()).into()) + .ok_or_else(|| Error::UnknownService(name.to_owned()).into()) } /// Look for a name as a pod first, and if that fails, look for it as a /// service. - pub fn pod_or_service<'a, 'b>( - &'a self, - name: &'b str, - ) -> Option> { + pub fn pod_or_service<'a>(&'a self, name: &str) -> Option> { if let Some(pod) = self.pod(name) { Some(PodOrService::Pod(pod)) } else if let Some((pod, service_name)) = self.service(name) { @@ -450,12 +451,12 @@ impl Project { /// Like `pod_or_service`, but returns an error if no pod or service of /// that name can be found. - pub fn pod_or_service_or_err<'a, 'b>( + pub fn pod_or_service_or_err<'a>( &'a self, - name: &'b str, + name: &str, ) -> Result> { self.pod_or_service(name) - .ok_or_else(|| ErrorKind::UnknownPodOrService(name.to_owned()).into()) + .ok_or_else(|| Error::UnknownPodOrService(name.to_owned()).into()) } /// Iterate over all targets in this project. @@ -474,7 +475,7 @@ impl Project { /// Like `target`, but returns an error if no each target is found. pub fn target_or_err(&self, name: &str) -> Result<&Target> { self.target(name) - .ok_or_else(|| ErrorKind::UnknownTarget(name.into()).into()) + .ok_or_else(|| Error::UnknownTarget(name.into()).into()) } /// Get the current target that we're using with this project. diff --git a/src/runtime_state.rs b/src/runtime_state.rs index 52721c97..a76c4833 100644 --- a/src/runtime_state.rs +++ b/src/runtime_state.rs @@ -24,7 +24,7 @@ impl RuntimeState { // until we debug all the Docker wire formats and undocumented // special cases. Self::for_project_inner(project) - .chain_err(|| ErrorKind::CouldNotGetRuntimeState) + .map_err(|e| e.context(Error::CouldNotGetRuntimeState)) } /// The actual implementation of `for_project`. @@ -32,27 +32,49 @@ impl RuntimeState { debug!("Querying Docker for running containers"); // Start a local `tokio` runtime for async calls. - let mut rt = runtime::Builder::new() - .basic_scheduler() + let rt = runtime::Builder::new_current_thread() .enable_all() .build()?; let name = project.compose_name(); let target = project.current_target().name().to_owned(); - let docker = boondock::Docker::connect_with_defaults()?; + let docker = bollard::Docker::connect_with_local_defaults() + .map_err(|e| anyhow::anyhow!("failed to connect to Docker: {}", e))?; let mut services = BTreeMap::new(); - let opts = boondock::ContainerListOptions::default().all(); - let containers = rt.block_on(docker.containers(opts))?; + use bollard::query_parameters::ListContainersOptionsBuilder; + let opts = ListContainersOptionsBuilder::default().all(true).build(); + let containers = rt + .block_on(docker.list_containers(Some(opts))) + .map_err(|e| anyhow::anyhow!("failed to list Docker containers: {}", e))?; for container in &containers { - let info = - rt.block_on(docker.container_info(container)) - .chain_err(|| { - format!("error looking up container {:?}", container.Id) - })?; - let labels = &info.Config.Labels; - if labels.get("com.docker.compose.project") == Some(&name) - && labels.get("io.fdy.cage.target") == Some(&target) + let container_id = container + .id + .as_ref() + .ok_or_else(|| anyhow::anyhow!("container missing id"))?; + let info = rt + .block_on(docker.inspect_container( + container_id, + None::, + )) + .map_err(|e| { + anyhow::anyhow!( + "error looking up container {:?}: {}", + container_id, + e + ) + })?; + let labels = &info + .config + .as_ref() + .and_then(|c| c.labels.as_ref()) + .ok_or_else(|| { + anyhow::anyhow!("container missing config or labels") + })?; + if labels.get("com.docker.compose.project").map(|s| s.as_str()) + == Some(&name) + && labels.get("io.fdy.cage.target").map(|s| s.as_str()) + == Some(&target) { if let Some(service) = labels.get("com.docker.compose.service") { let our_info = ContainerInfo::new(&info)?; @@ -121,44 +143,68 @@ pub struct ContainerInfo { impl ContainerInfo { /// Construct our summary from the raw data returned by Docker. - fn new(info: &boondock::container::ContainerInfo) -> Result { + fn new(info: &bollard::models::ContainerInspectResponse) -> Result { // Was this a one-off container? - let one_off_label = info.Config.Labels.get("com.docker.compose.oneoff"); - let is_one_off = Some("True") == one_off_label.map(|s| &s[..]); + let one_off_label = info + .config + .as_ref() + .and_then(|c| c.labels.as_ref()) + .and_then(|labels| labels.get("com.docker.compose.oneoff")); + let is_one_off = one_off_label.map(|s| s.as_str()) == Some("True"); // Get an IP address for this running container. - let raw_ip_addr = &info.NetworkSettings.IPAddress[..]; + let raw_ip_addr = info + .network_settings + .as_ref() + .and_then(|ns| ns.ip_address.as_ref()) + .map(|s| s.as_str()) + .unwrap_or(""); let ip_addr = if !raw_ip_addr.is_empty() { - Some( - raw_ip_addr - .parse() - .chain_err(|| ErrorKind::parse("IP address", raw_ip_addr))?, - ) + Some(raw_ip_addr.parse().map_err(|e| { + anyhow::Error::new(e).context(Error::parse("IP address", raw_ip_addr)) + })?) } else { None }; // Get the listening network ports. let mut ports = vec![]; - if let Some(port_strs) = &info.NetworkSettings.Ports { - for port_str in port_strs.keys() { - lazy_static! { - static ref TCP_PORT: Regex = Regex::new(r#"^(\d+)/tcp$"#).unwrap(); - } - if let Some(caps) = TCP_PORT.captures(port_str) { - let port = - caps.get(1).unwrap().as_str().parse().chain_err(|| { - ErrorKind::parse("TCP port", port_str.clone()) - })?; - ports.push(port); + if let Some(network_settings) = &info.network_settings { + if let Some(port_map) = &network_settings.ports { + for port_str in port_map.keys() { + lazy_static! { + static ref TCP_PORT: Regex = + Regex::new(r#"^(\d+)/tcp$"#).unwrap(); + } + if let Some(caps) = TCP_PORT.captures(port_str) { + let port = + caps.get(1).unwrap().as_str().parse().map_err(|e| { + anyhow::Error::new(e).context(Error::parse( + "TCP port", + port_str.clone(), + )) + })?; + ports.push(port); + } } } } + let name = info + .name + .as_ref() + .ok_or_else(|| anyhow::anyhow!("container missing name"))? + .to_owned(); + + let state = info + .state + .as_ref() + .ok_or_else(|| anyhow::anyhow!("container missing state"))?; + Ok(ContainerInfo { - name: info.Name.to_owned(), + name, is_one_off, - state: ContainerStatus::new(&info.State), + state: ContainerStatus::new(state), ip_addr, container_tcp_ports: ports, }) @@ -194,7 +240,7 @@ impl ContainerInfo { .map(|port| net::SocketAddr::new(addr, *port)) .collect() }) - .unwrap_or_else(Vec::new) + .unwrap_or_default() } /// Is this container listening to its ports? @@ -233,14 +279,23 @@ pub enum ContainerStatus { impl ContainerStatus { /// Create a new `ContainerStatus` from Docker data. - fn new(state: &boondock::container::State) -> ContainerStatus { - match &state.Status[..] { - "created" => ContainerStatus::Created, - "restarting" => ContainerStatus::Restarting, - "running" => ContainerStatus::Running, - "paused" => ContainerStatus::Paused, - "exited" if state.ExitCode == 0 => ContainerStatus::Done, - "exited" => ContainerStatus::Exited(state.ExitCode), + fn new(state: &bollard::models::ContainerState) -> ContainerStatus { + use bollard::models::ContainerStateStatusEnum; + + let status = state.status.as_ref(); + let exit_code = state.exit_code.unwrap_or(0); + + match status { + Some(ContainerStateStatusEnum::CREATED) => ContainerStatus::Created, + Some(ContainerStateStatusEnum::RESTARTING) => ContainerStatus::Restarting, + Some(ContainerStateStatusEnum::RUNNING) => ContainerStatus::Running, + Some(ContainerStateStatusEnum::PAUSED) => ContainerStatus::Paused, + Some(ContainerStateStatusEnum::EXITED) if exit_code == 0 => { + ContainerStatus::Done + } + Some(ContainerStateStatusEnum::EXITED) => { + ContainerStatus::Exited(exit_code) + } _ => ContainerStatus::Other, } } diff --git a/src/serde_helpers.rs b/src/serde_helpers.rs index 81572535..4152cd66 100644 --- a/src/serde_helpers.rs +++ b/src/serde_helpers.rs @@ -9,33 +9,42 @@ use std::marker::PhantomData; use std::path::Path; use std::str::FromStr; -use crate::errors::{self, ErrorKind, ResultExt}; +use crate::errors::{Error, Result}; use crate::util::ConductorPathExt; /// Load a YAML file using `serde`, and generate the best error we can if /// it fails. -pub fn load_yaml(path: &Path) -> Result +pub fn load_yaml(path: &Path) -> Result where T: DeserializeOwned, { - let mkerr = || ErrorKind::CouldNotReadFile(path.to_owned()); - let f = fs::File::open(&path).chain_err(&mkerr)?; - serde_yaml::from_reader(io::BufReader::new(f)).chain_err(&mkerr) + let f = fs::File::open(path).map_err(|e| { + anyhow::Error::new(e).context(Error::CouldNotReadFile(path.to_owned())) + })?; + serde_yaml::from_reader(io::BufReader::new(f)).map_err(|e| { + anyhow::Error::new(e).context(Error::CouldNotReadFile(path.to_owned())) + }) } /// Write `data` to `path` in YAML format. -pub fn dump_yaml(path: &Path, data: &T) -> Result<(), errors::Error> +pub fn dump_yaml(path: &Path, data: &T) -> Result<()> where T: Serialize, { - let mkerr = || ErrorKind::CouldNotWriteFile(path.to_owned()); - path.with_guaranteed_parent().chain_err(&mkerr)?; - let f = fs::File::create(&path).chain_err(&mkerr)?; - serde_yaml::to_writer(&mut io::BufWriter::new(f), data).chain_err(&mkerr) + path.with_guaranteed_parent() + .map_err(|e| e.context(Error::CouldNotWriteFile(path.to_owned())))?; + let f = fs::File::create(path).map_err(|e| { + anyhow::Error::new(e).context(Error::CouldNotWriteFile(path.to_owned())) + })?; + serde_yaml::to_writer(&mut io::BufWriter::new(f), data).map_err(|e| { + anyhow::Error::new(e).context(Error::CouldNotWriteFile(path.to_owned())) + }) } /// Deserialize a type that we can parse using `FromStr`. -pub fn deserialize_parsable<'de, D, T>(deserializer: D) -> Result +pub fn deserialize_parsable<'de, D, T>( + deserializer: D, +) -> std::result::Result where D: Deserializer<'de>, T: FromStr, @@ -54,7 +63,7 @@ where /// [issue]: https://github.com/serde-rs/serde/issues/576 pub fn deserialize_parsable_opt<'de, D, T>( deserializer: D, -) -> Result, D::Error> +) -> std::result::Result, D::Error> where D: Deserializer<'de>, T: FromStr, @@ -70,7 +79,7 @@ where T: FromStr, ::Err: Display, { - fn deserialize(deserializer: D) -> Result + fn deserialize(deserializer: D) -> std::result::Result where D: Deserializer<'de>, { @@ -84,7 +93,7 @@ where { type Value = Wrap; - fn visit_none(self) -> Result + fn visit_none(self) -> std::result::Result where E: serde::de::Error, { @@ -94,7 +103,7 @@ where fn visit_some( self, deserializer: D, - ) -> Result + ) -> std::result::Result where D: Deserializer<'de>, { diff --git a/src/service_locations.rs b/src/service_locations.rs index 9e95d4d2..36a12638 100644 --- a/src/service_locations.rs +++ b/src/service_locations.rs @@ -66,9 +66,9 @@ impl ServiceLocations { } /// Find a service by name. - pub fn find<'a>(&self, service_name: &'a str) -> Option<(&str, &str)> { + pub fn find(&self, service_name: &str) -> Option<(&str, &str)> { self.locations .get(service_name) - .map(|&(ref pod, ref service)| (&pod[..], &service[..])) + .map(|(pod, service)| (&pod[..], &service[..])) } } diff --git a/src/sources.rs b/src/sources.rs index 2f8f0cea..8670fc1f 100644 --- a/src/sources.rs +++ b/src/sources.rs @@ -1,7 +1,7 @@ //! APIs for working with the source code associated with a `Project`'s //! Docker images. -use compose_yml::v2 as dc; +use faraday_compose_yml::v2 as dc; use std::collections::btree_map; use std::collections::BTreeMap; #[cfg(test)] @@ -34,7 +34,7 @@ struct SourceConfig { /// The local or remote `context` for this source tree. We don't /// really want to use `dc::RawOr` here, but it's the easiest way to /// get this to work with serde, because that's how it works in - /// `docker-compose.yml` files, and that's what our `compose_yml` + /// `docker-compose.yml` files, and that's what our `faraday_compose_yml` /// library supports. context: dc::RawOr, } @@ -145,9 +145,7 @@ impl Sources { if *context != context.without_repository_subdirectory() { // We might actually be able to handle this case, but lib sources // are already awkward enough without adding more features. - return Err( - ErrorKind::LibHasRepoSubdirectory(lib_key.clone()).into() - ); + return Err(Error::LibHasRepoSubdirectory(lib_key.clone()).into()); } let alias = Self::add_source(&mut sources, &mounted, context)?; lib_keys.insert(lib_key.clone(), alias); @@ -193,7 +191,7 @@ impl Sources { /// `io.fdy.cage.lib.`. pub fn find_by_lib_key(&self, lib_key: &str) -> Option<&Source> { match self.lib_keys.get(lib_key) { - Some(alias) => self.find_by_alias(&alias), + Some(alias) => self.find_by_alias(alias), None => None, } } @@ -330,7 +328,10 @@ impl Source { self.set_mounted(true); Ok(()) } else { - Err(format!("'{}' is not a git repository", &self.context).into()) + Err(anyhow::anyhow!( + "'{}' is not a git repository", + &self.context + )) } } diff --git a/src/template.rs b/src/template.rs index 2ce7c29d..2a2350a1 100644 --- a/src/template.rs +++ b/src/template.rs @@ -38,31 +38,63 @@ impl Template { /// Create a new template, loading it from a subdirectory of `data/` /// specified by `template_name`. pub fn new(name: &str) -> Result