From ec1c6fcffaf8ac01e41f211632fbd07a5d7b39ae Mon Sep 17 00:00:00 2001 From: daimond113 <72147841+daimond113@users.noreply.github.com> Date: Mon, 4 Mar 2024 21:18:49 +0100 Subject: [PATCH] feat: :tada: initial commit --- .dockerignore | 6 + .github/workflows/release.yaml | 101 + .github/workflows/test-and-lint.yaml | 35 + .gitignore | 7 + Cargo.lock | 5550 ++++++++++++++++++++++++++ Cargo.toml | 56 + Dockerfile | 9 + README.md | 22 + cliff.toml | 86 + fly.toml | 31 + registry/.env.example | 11 + registry/Cargo.lock | 3201 +++++++++++++++ registry/Cargo.toml | 29 + registry/src/endpoints/mod.rs | 8 + registry/src/endpoints/packages.rs | 208 + registry/src/endpoints/search.rs | 56 + registry/src/errors.rs | 71 + registry/src/main.rs | 272 ++ rust-toolchain.toml | 2 + src/cli/auth.rs | 110 + src/cli/config.rs | 66 + src/cli/mod.rs | 3 + src/cli/root.rs | 281 ++ src/dependencies/git.rs | 161 + src/dependencies/mod.rs | 182 + src/dependencies/registry.rs | 125 + src/dependencies/resolution.rs | 442 ++ src/index.rs | 558 +++ src/lib.rs | 48 + src/linking_file.rs | 284 ++ src/main.rs | 217 + src/manifest.rs | 180 + src/multithread.rs | 33 + src/package_name.rs | 151 + src/patches.rs | 210 + src/project.rs | 219 + tests/prelude.rs | 99 + tests/resolver.rs | 118 + 38 files changed, 13248 insertions(+) create mode 100644 .dockerignore create mode 100644 .github/workflows/release.yaml create mode 100644 .github/workflows/test-and-lint.yaml create mode 100644 .gitignore create mode 100644 Cargo.lock create mode 100644 Cargo.toml create mode 100644 Dockerfile create mode 100644 README.md create mode 100644 cliff.toml create mode 100644 fly.toml create mode 100644 registry/.env.example create mode 100644 registry/Cargo.lock create mode 100644 registry/Cargo.toml create mode 100644 registry/src/endpoints/mod.rs create mode 100644 registry/src/endpoints/packages.rs create mode 100644 registry/src/endpoints/search.rs create mode 100644 registry/src/errors.rs create mode 100644 registry/src/main.rs create mode 100644 rust-toolchain.toml create mode 100644 src/cli/auth.rs create mode 100644 src/cli/config.rs create mode 100644 src/cli/mod.rs create mode 100644 src/cli/root.rs create mode 100644 src/dependencies/git.rs create mode 100644 src/dependencies/mod.rs create mode 100644 src/dependencies/registry.rs create mode 100644 src/dependencies/resolution.rs create mode 100644 src/index.rs create mode 100644 src/lib.rs create mode 100644 src/linking_file.rs create mode 100644 src/main.rs create mode 100644 src/manifest.rs create mode 100644 src/multithread.rs create mode 100644 src/package_name.rs create mode 100644 src/patches.rs create mode 100644 src/project.rs create mode 100644 tests/prelude.rs create mode 100644 tests/resolver.rs diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..0f9adde --- /dev/null +++ b/.dockerignore @@ -0,0 +1,6 @@ +* +!src +!registry +!Cargo.lock +!Cargo.toml +!rust-toolchain.toml \ No newline at end of file diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml new file mode 100644 index 0000000..213b826 --- /dev/null +++ b/.github/workflows/release.yaml @@ -0,0 +1,101 @@ +name: Release +on: + push: + tags: + - v* +jobs: + build: + strategy: + matrix: + include: + - os: ubuntu-latest + host: linux + label: linux-x86_64 + target: x86_64-unknown-linux-gnu + + - os: windows-latest + host: windows + label: windows-x86_64 + target: x86_64-pc-windows-msvc + + - os: macos-latest + host: macos + label: macos-x86_64 + target: x86_64-apple-darwin + + - os: macos-latest-xlarge + host: macos + label: macos-aarch64 + target: aarch64-apple-darwin + runs-on: ${{ matrix.os }} + name: Build for ${{ matrix.label }} + steps: + - uses: actions/checkout@v4 + - name: Set up Rust + uses: moonrepo/setup-rust@v1 + with: + targets: ${{ matrix.target }} + + - name: Set env + shell: bash + run: | + BIN_NAME=pesde + ARCHIVE_NAME=$BIN_NAME-$(echo ${{ github.ref_name }} | cut -c 2-)-${{ matrix.label }}.zip + + echo "BIN_NAME=$BIN_NAME" >> $GITHUB_ENV + echo "ARCHIVE_NAME=$ARCHIVE_NAME" >> $GITHUB_ENV + + - name: Build + run: cargo build --bins --all-features --release --target ${{ matrix.target }} --locked + + - name: Archive + shell: bash + run: | + if [ ${{ matrix.host }} = "windows" ]; then + cp target/${{ matrix.target }}/release/${{ env.BIN_NAME }}.exe ${{ env.BIN_NAME }}.exe + 7z a ${{ env.ARCHIVE_NAME }} ${{ env.BIN_NAME }}.exe + else + cp target/${{ matrix.target }}/release/${{ env.BIN_NAME }} ${{ env.BIN_NAME }} + zip -r ${{ env.ARCHIVE_NAME }} ${{ env.BIN_NAME }} + fi + + - name: Upload assets + uses: actions/upload-artifact@v4 + with: + name: ${{ env.ARCHIVE_NAME }} + path: ${{ env.ARCHIVE_NAME }} + + create_release: + name: Create Release + runs-on: ubuntu-latest + permissions: + contents: write + pull-requests: read + needs: [build] + steps: + - uses: actions/checkout@v4 + with: + fetch-depth: 0 + - uses: actions/download-artifact@v4 + with: + path: artifacts + merge-multiple: true + + - name: Generate a changelog + uses: orhun/git-cliff-action@v3 + id: git-cliff + with: + config: cliff.toml + args: --verbose --current --strip header --github-repo ${{ github.repository }} --github-token ${{ secrets.GITHUB_TOKEN }} + + - name: Create Release + id: create_release + uses: softprops/action-gh-release@v1 + with: + token: ${{ secrets.GITHUB_TOKEN }} + tag_name: ${{ github.ref_name }} + name: ${{ github.ref_name }} + body: ${{ steps.git-cliff.outputs.content }} + draft: true + prerelease: false + files: artifacts/* \ No newline at end of file diff --git a/.github/workflows/test-and-lint.yaml b/.github/workflows/test-and-lint.yaml new file mode 100644 index 0000000..dcb8caa --- /dev/null +++ b/.github/workflows/test-and-lint.yaml @@ -0,0 +1,35 @@ +name: Test & Lint +on: + - push + - pull_request + +env: + CARGO_TERM_COLOR: always + +jobs: + lint: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - name: Set up Rust + uses: moonrepo/setup-rust@v1 + with: + bins: cargo-tarpaulin + components: rustfmt, clippy + + - name: Run tests + run: cargo test --all + + - name: Check formatting + run: cargo fmt --all -- --check + + - name: Run clippy + run: cargo clippy --all-targets --all-features -- -D warnings + + - name: Generate coverage report + run: cargo tarpaulin --all-features --out xml --exclude-files src/cli/* --exclude-files registry/* --exclude-files src/main.rs --skip-clean + + - name: Upload coverage reports to Codecov + uses: codecov/codecov-action@v4.0.1 + with: + token: ${{ secrets.CODECOV_TOKEN }} \ No newline at end of file diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..0302135 --- /dev/null +++ b/.gitignore @@ -0,0 +1,7 @@ +**/target +**/.env +.idea +cobertura.xml +tarpaulin-report.html +build_rs_cov.profraw +registry/cache \ No newline at end of file diff --git a/Cargo.lock b/Cargo.lock new file mode 100644 index 0000000..14768c1 --- /dev/null +++ b/Cargo.lock @@ -0,0 +1,5550 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "actix-codec" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5f7b0a21988c1bf877cf4759ef5ddaac04c1c9fe808c9142ecb78ba97d97a28a" +dependencies = [ + "bitflags 2.4.2", + "bytes", + "futures-core", + "futures-sink", + "memchr", + "pin-project-lite", + "tokio", + "tokio-util", + "tracing", +] + +[[package]] +name = "actix-cors" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f9e772b3bcafe335042b5db010ab7c09013dad6eac4915c91d8d50902769f331" +dependencies = [ + "actix-utils", + "actix-web", + "derive_more", + "futures-util", + "log", + "once_cell", + "smallvec", +] + +[[package]] +name = "actix-http" +version = "3.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d223b13fd481fc0d1f83bb12659ae774d9e3601814c68a0bc539731698cca743" +dependencies = [ + "actix-codec", + "actix-rt", + "actix-service", + "actix-utils", + "ahash", + "base64 0.21.7", + "bitflags 2.4.2", + "brotli", + "bytes", + "bytestring", + "derive_more", + "encoding_rs", + "flate2", + "futures-core", + "h2", + "http", + "httparse", + "httpdate", + "itoa", + "language-tags", + "local-channel", + "mime", + "percent-encoding", + "pin-project-lite", + "rand", + "sha1 0.10.6", + "smallvec", + "tokio", + "tokio-util", + "tracing", + "zstd 0.13.0", +] + +[[package]] +name = "actix-macros" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e01ed3140b2f8d422c68afa1ed2e85d996ea619c988ac834d255db32138655cb" +dependencies = [ + "quote", + "syn 2.0.52", +] + +[[package]] +name = "actix-multipart" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3b960e2aea75f49c8f069108063d12a48d329fc8b60b786dfc7552a9d5918d2d" +dependencies = [ + "actix-multipart-derive", + "actix-utils", + "actix-web", + "bytes", + "derive_more", + "futures-core", + "futures-util", + "httparse", + "local-waker", + "log", + "memchr", + "mime", + "serde", + "serde_json", + "serde_plain", + "tempfile", + "tokio", +] + +[[package]] +name = "actix-multipart-derive" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0a0a77f836d869f700e5b47ac7c3c8b9c8bc82e4aec861954c6198abee3ebd4d" +dependencies = [ + "darling", + "parse-size", + "proc-macro2", + "quote", + "syn 2.0.52", +] + +[[package]] +name = "actix-router" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d22475596539443685426b6bdadb926ad0ecaefdfc5fb05e5e3441f15463c511" +dependencies = [ + "bytestring", + "http", + "regex", + "serde", + "tracing", +] + +[[package]] +name = "actix-rt" +version = "2.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "28f32d40287d3f402ae0028a9d54bef51af15c8769492826a69d28f81893151d" +dependencies = [ + "futures-core", + "tokio", +] + +[[package]] +name = "actix-server" +version = "2.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3eb13e7eef0423ea6eab0e59f6c72e7cb46d33691ad56a726b3cd07ddec2c2d4" +dependencies = [ + "actix-rt", + "actix-service", + "actix-utils", + "futures-core", + "futures-util", + "mio", + "socket2 0.5.6", + "tokio", + "tracing", +] + +[[package]] +name = "actix-service" +version = "2.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3b894941f818cfdc7ccc4b9e60fa7e53b5042a2e8567270f9147d5591893373a" +dependencies = [ + "futures-core", + "paste", + "pin-project-lite", +] + +[[package]] +name = "actix-utils" +version = "3.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "88a1dcdff1466e3c2488e1cb5c36a71822750ad43839937f85d2f4d9f8b705d8" +dependencies = [ + "local-waker", + "pin-project-lite", +] + +[[package]] +name = "actix-web" +version = "4.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "43a6556ddebb638c2358714d853257ed226ece6023ef9364f23f0c70737ea984" +dependencies = [ + "actix-codec", + "actix-http", + "actix-macros", + "actix-router", + "actix-rt", + "actix-server", + "actix-service", + "actix-utils", + "actix-web-codegen", + "ahash", + "bytes", + "bytestring", + "cfg-if", + "cookie 0.16.2", + "derive_more", + "encoding_rs", + "futures-core", + "futures-util", + "itoa", + "language-tags", + "log", + "mime", + "once_cell", + "pin-project-lite", + "regex", + "serde", + "serde_json", + "serde_urlencoded", + "smallvec", + "socket2 0.5.6", + "time 0.3.34", + "url", +] + +[[package]] +name = "actix-web-codegen" +version = "4.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eb1f50ebbb30eca122b188319a4398b3f7bb4a8cdf50ecfb73bfc6a3c3ce54f5" +dependencies = [ + "actix-router", + "proc-macro2", + "quote", + "syn 2.0.52", +] + +[[package]] +name = "actix-web-httpauth" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d613edf08a42ccc6864c941d30fe14e1b676a77d16f1dbadc1174d065a0a775" +dependencies = [ + "actix-utils", + "actix-web", + "base64 0.21.7", + "futures-core", + "futures-util", + "log", + "pin-project-lite", +] + +[[package]] +name = "addr2line" +version = "0.21.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a30b2e23b9e17a9f90641c7ab1549cd9b44f296d3ccbf309d2863cfe398a0cb" +dependencies = [ + "gimli", +] + +[[package]] +name = "adler" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" + +[[package]] +name = "aes" +version = "0.7.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9e8b47f52ea9bae42228d07ec09eb676433d7c4ed1ebdf0f1d1c29ed446f1ab8" +dependencies = [ + "cfg-if", + "cipher", + "cpufeatures", + "opaque-debug", +] + +[[package]] +name = "ahash" +version = "0.8.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e89da841a80418a9b391ebaea17f5c112ffaaa96f621d2c285b5174da76b9011" +dependencies = [ + "cfg-if", + "getrandom 0.2.12", + "once_cell", + "version_check", + "zerocopy", +] + +[[package]] +name = "aho-corasick" +version = "1.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b2969dcb958b36655471fc61f7e416fa76033bdd4bfed0678d8fee1e2d07a1f0" +dependencies = [ + "memchr", +] + +[[package]] +name = "alloc-no-stdlib" +version = "2.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cc7bb162ec39d46ab1ca8c77bf72e890535becd1751bb45f64c597edb4c8c6b3" + +[[package]] +name = "alloc-stdlib" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94fb8275041c72129eb51b7d0322c29b8387a0386127718b096429201a5d6ece" +dependencies = [ + "alloc-no-stdlib", +] + +[[package]] +name = "allocator-api2" +version = "0.2.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0942ffc6dcaadf03badf6e6a2d0228460359d5e34b57ccdc720b7382dfbd5ec5" + +[[package]] +name = "android-tzdata" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e999941b234f3131b00bc13c22d06e8c5ff726d1b6318ac7eb276997bbb4fef0" + +[[package]] +name = "android_system_properties" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311" +dependencies = [ + "libc", +] + +[[package]] +name = "anstream" +version = "0.6.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d96bd03f33fe50a863e394ee9718a706f988b9079b20c3784fb726e7678b62fb" +dependencies = [ + "anstyle", + "anstyle-parse", + "anstyle-query", + "anstyle-wincon", + "colorchoice", + "utf8parse", +] + +[[package]] +name = "anstyle" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8901269c6307e8d93993578286ac0edf7f195079ffff5ebdeea6a59ffb7e36bc" + +[[package]] +name = "anstyle-parse" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c75ac65da39e5fe5ab759307499ddad880d724eed2f6ce5b5e8a26f4f387928c" +dependencies = [ + "utf8parse", +] + +[[package]] +name = "anstyle-query" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e28923312444cdd728e4738b3f9c9cac739500909bb3d3c94b43551b16517648" +dependencies = [ + "windows-sys 0.52.0", +] + +[[package]] +name = "anstyle-wincon" +version = "3.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1cd54b81ec8d6180e24654d0b371ad22fc3dd083b6ff8ba325b72e00c87660a7" +dependencies = [ + "anstyle", + "windows-sys 0.52.0", +] + +[[package]] +name = "anyhow" +version = "1.0.80" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5ad32ce52e4161730f7098c077cd2ed6229b5804ccf99e5366be1ab72a98b4e1" + +[[package]] +name = "arc-swap" +version = "1.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7b3d0060af21e8d11a926981cc00c6c1541aa91dd64b9f881985c3da1094425f" + +[[package]] +name = "arrayref" +version = "0.3.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6b4930d2cb77ce62f89ee5d5289b4ac049559b1c45539271f5ed4fdc7db34545" + +[[package]] +name = "arrayvec" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "23b62fc65de8e4e7f52534fb52b0f3ed04746ae267519eef2a83941e8085068b" + +[[package]] +name = "arrayvec" +version = "0.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "96d30a06541fbafbc7f82ed10c06164cfbd2c401138f6addd8404629c4b16711" + +[[package]] +name = "async-broadcast" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7c48ccdbf6ca6b121e0f586cbc0e73ae440e56c67c30fa0873b4e110d9c26d2b" +dependencies = [ + "event-listener 2.5.3", + "futures-core", +] + +[[package]] +name = "async-channel" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f28243a43d821d11341ab73c80bed182dc015c514b951616cf79bd4af39af0c3" +dependencies = [ + "concurrent-queue", + "event-listener 5.2.0", + "event-listener-strategy 0.5.0", + "futures-core", + "pin-project-lite", +] + +[[package]] +name = "async-compression" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a116f46a969224200a0a97f29cfd4c50e7534e4b4826bd23ea2c3c533039c82c" +dependencies = [ + "brotli", + "flate2", + "futures-core", + "memchr", + "pin-project-lite", + "tokio", +] + +[[package]] +name = "async-executor" +version = "1.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "17ae5ebefcc48e7452b4987947920dac9450be1110cadf34d1b8c116bdbaf97c" +dependencies = [ + "async-lock 3.3.0", + "async-task", + "concurrent-queue", + "fastrand 2.0.1", + "futures-lite 2.2.0", + "slab", +] + +[[package]] +name = "async-fs" +version = "1.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "279cf904654eeebfa37ac9bb1598880884924aab82e290aa65c9e77a0e142e06" +dependencies = [ + "async-lock 2.8.0", + "autocfg", + "blocking", + "futures-lite 1.13.0", +] + +[[package]] +name = "async-io" +version = "1.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fc5b45d93ef0529756f812ca52e44c221b35341892d3dcc34132ac02f3dd2af" +dependencies = [ + "async-lock 2.8.0", + "autocfg", + "cfg-if", + "concurrent-queue", + "futures-lite 1.13.0", + "log", + "parking", + "polling 2.8.0", + "rustix 0.37.27", + "slab", + "socket2 0.4.10", + "waker-fn", +] + +[[package]] +name = "async-io" +version = "2.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f97ab0c5b00a7cdbe5a371b9a782ee7be1316095885c8a4ea1daf490eb0ef65" +dependencies = [ + "async-lock 3.3.0", + "cfg-if", + "concurrent-queue", + "futures-io", + "futures-lite 2.2.0", + "parking", + "polling 3.5.0", + "rustix 0.38.31", + "slab", + "tracing", + "windows-sys 0.52.0", +] + +[[package]] +name = "async-lock" +version = "2.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "287272293e9d8c41773cec55e365490fe034813a2f172f502d6ddcf75b2f582b" +dependencies = [ + "event-listener 2.5.3", +] + +[[package]] +name = "async-lock" +version = "3.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d034b430882f8381900d3fe6f0aaa3ad94f2cb4ac519b429692a1bc2dda4ae7b" +dependencies = [ + "event-listener 4.0.3", + "event-listener-strategy 0.4.0", + "pin-project-lite", +] + +[[package]] +name = "async-process" +version = "1.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ea6438ba0a08d81529c69b36700fa2f95837bfe3e776ab39cde9c14d9149da88" +dependencies = [ + "async-io 1.13.0", + "async-lock 2.8.0", + "async-signal", + "blocking", + "cfg-if", + "event-listener 3.1.0", + "futures-lite 1.13.0", + "rustix 0.38.31", + "windows-sys 0.48.0", +] + +[[package]] +name = "async-recursion" +version = "1.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5fd55a5ba1179988837d24ab4c7cc8ed6efdeff578ede0416b4225a5fca35bd0" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.52", +] + +[[package]] +name = "async-signal" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9e47d90f65a225c4527103a8d747001fc56e375203592b25ad103e1ca13124c5" +dependencies = [ + "async-io 2.3.1", + "async-lock 2.8.0", + "atomic-waker", + "cfg-if", + "futures-core", + "futures-io", + "rustix 0.38.31", + "signal-hook-registry", + "slab", + "windows-sys 0.48.0", +] + +[[package]] +name = "async-task" +version = "4.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fbb36e985947064623dbd357f727af08ffd077f93d696782f3c56365fa2e2799" + +[[package]] +name = "async-trait" +version = "0.1.77" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c980ee35e870bd1a4d2c8294d4c04d0499e67bca1e4b5cefcc693c2fa00caea9" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.52", +] + +[[package]] +name = "atomic-waker" +version = "1.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1505bd5d3d116872e7271a6d4e16d81d0c8570876c8de68093a09ac269d8aac0" + +[[package]] +name = "auth-git2" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41e7771d4ab6635cbd685ce8db215b29c78a468098126de77c57f3b2e6eb3757" +dependencies = [ + "dirs 5.0.1", + "git2", + "terminal-prompt", +] + +[[package]] +name = "autocfg" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" + +[[package]] +name = "backtrace" +version = "0.3.69" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2089b7e3f35b9dd2d0ed921ead4f6d318c27680d4a5bd167b3ee120edb105837" +dependencies = [ + "addr2line", + "cc", + "cfg-if", + "libc", + "miniz_oxide", + "object", + "rustc-demangle", +] + +[[package]] +name = "base-x" +version = "0.2.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4cbbc9d0964165b47557570cce6c952866c2678457aca742aafc9fb771d30270" + +[[package]] +name = "base64" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8" + +[[package]] +name = "base64" +version = "0.21.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d297deb1925b89f2ccc13d7635fa0714f12c87adce1c75356b39ca9b7178567" + +[[package]] +name = "beef" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3a8241f3ebb85c056b509d4327ad0358fbbba6ffb340bf388f26350aeda225b1" + +[[package]] +name = "bitflags" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" + +[[package]] +name = "bitflags" +version = "2.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed570934406eb16438a4e976b1b4500774099c13b8cb96eec99f620f05090ddf" + +[[package]] +name = "bitpacking" +version = "0.8.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a8c7d2ac73c167c06af4a5f37e6e59d84148d57ccbe4480b76f0273eefea82d7" +dependencies = [ + "crunchy", +] + +[[package]] +name = "blake2b_simd" +version = "0.5.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "afa748e348ad3be8263be728124b24a24f268266f6f5d58af9d75f6a40b5c587" +dependencies = [ + "arrayref", + "arrayvec 0.5.2", + "constant_time_eq 0.1.5", +] + +[[package]] +name = "blake3" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0231f06152bf547e9c2b5194f247cd97aacf6dcd8b15d8e5ec0663f64580da87" +dependencies = [ + "arrayref", + "arrayvec 0.7.4", + "cc", + "cfg-if", + "constant_time_eq 0.3.0", +] + +[[package]] +name = "block-buffer" +version = "0.10.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71" +dependencies = [ + "generic-array", +] + +[[package]] +name = "block-modes" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2cb03d1bed155d89dce0f845b7899b18a9a163e148fd004e1c28421a783e2d8e" +dependencies = [ + "block-padding", + "cipher", +] + +[[package]] +name = "block-padding" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8d696c370c750c948ada61c69a0ee2cbbb9c50b1019ddb86d9317157a99c2cae" + +[[package]] +name = "blocking" +version = "1.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a37913e8dc4ddcc604f0c6d3bf2887c995153af3611de9e23c352b44c1b9118" +dependencies = [ + "async-channel", + "async-lock 3.3.0", + "async-task", + "fastrand 2.0.1", + "futures-io", + "futures-lite 2.2.0", + "piper", + "tracing", +] + +[[package]] +name = "brotli" +version = "3.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "516074a47ef4bce09577a3b379392300159ce5b1ba2e501ff1c819950066100f" +dependencies = [ + "alloc-no-stdlib", + "alloc-stdlib", + "brotli-decompressor", +] + +[[package]] +name = "brotli-decompressor" +version = "2.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4e2e4afe60d7dd600fdd3de8d0f08c2b7ec039712e3b6137ff98b7004e82de4f" +dependencies = [ + "alloc-no-stdlib", + "alloc-stdlib", +] + +[[package]] +name = "bstr" +version = "1.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05efc5cfd9110c8416e471df0e96702d58690178e206e61b7173706673c93706" +dependencies = [ + "memchr", + "serde", +] + +[[package]] +name = "bumpalo" +version = "3.15.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ea184aa71bb362a1157c896979544cc23974e08fd265f29ea96b59f0b4a555b" + +[[package]] +name = "bytecount" +version = "0.6.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e1e5f035d16fc623ae5f74981db80a439803888314e3a555fd6f04acd51a3205" + +[[package]] +name = "byteorder" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fc10e8cc6b2580fda3f36eb6dc5316657f812a3df879a44a66fc9f0fdbc4855" + +[[package]] +name = "byteorder" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" + +[[package]] +name = "bytes" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a2bd12c1caf447e69cd4528f47f94d203fd2582878ecb9e9465484c4148a8223" + +[[package]] +name = "bytestring" +version = "1.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "74d80203ea6b29df88012294f62733de21cfeab47f17b41af3a38bc30a03ee72" +dependencies = [ + "bytes", +] + +[[package]] +name = "cc" +version = "1.0.83" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1174fb0b6ec23863f8b971027804a42614e347eafb0a95bf0b12cdae21fc4d0" +dependencies = [ + "jobserver", + "libc", +] + +[[package]] +name = "census" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4f4c707c6a209cbe82d10abd08e1ea8995e9ea937d2550646e02798948992be0" + +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + +[[package]] +name = "chrono" +version = "0.4.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5bc015644b92d5890fab7489e49d21f879d5c990186827d42ec511919404f38b" +dependencies = [ + "android-tzdata", + "iana-time-zone", + "js-sys", + "num-traits", + "wasm-bindgen", + "windows-targets 0.52.4", +] + +[[package]] +name = "chrono_lc" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "809c968b91b4949802fba00279fd0610158cbb2ae5f10663f0c3d5331f88d6d6" +dependencies = [ + "chrono", + "lazy_static", + "num-integer", + "serde", + "serde_derive", + "serde_json", + "walkdir", +] + +[[package]] +name = "cipher" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7ee52072ec15386f770805afd189a01c8841be8696bed250fa2f13c4c0d6dfb7" +dependencies = [ + "generic-array", +] + +[[package]] +name = "clap" +version = "4.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c918d541ef2913577a0f9566e9ce27cb35b6df072075769e0b26cb5a554520da" +dependencies = [ + "clap_builder", + "clap_derive", +] + +[[package]] +name = "clap_builder" +version = "4.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9f3e7391dad68afb0c2ede1bf619f579a3dc9c2ec67f089baa397123a2f3d1eb" +dependencies = [ + "anstream", + "anstyle", + "clap_lex", + "strsim 0.11.0", +] + +[[package]] +name = "clap_derive" +version = "4.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "307bc0538d5f0f83b8248db3087aa92fe504e4691294d0c96c0eabc33f47ba47" +dependencies = [ + "heck", + "proc-macro2", + "quote", + "syn 2.0.52", +] + +[[package]] +name = "clap_lex" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "98cc8fbded0c607b7ba9dd60cd98df59af97e84d24e49c8557331cfc26d301ce" + +[[package]] +name = "clipboard-win" +version = "5.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "12f9a0700e0127ba15d1d52dd742097f821cd9c65939303a44d970465040a297" +dependencies = [ + "error-code", +] + +[[package]] +name = "colorchoice" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "acbf1af155f9b9ef647e42cdc158db4b64a1b61f743629225fde6f3e0be2a7c7" + +[[package]] +name = "concurrent-queue" +version = "2.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d16048cd947b08fa32c24458a22f5dc5e835264f689f4f5653210c69fd107363" +dependencies = [ + "crossbeam-utils", +] + +[[package]] +name = "console" +version = "0.15.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0e1f83fc076bd6dd27517eacdf25fef6c4dfe5f1d7448bafaaf3a26f13b5e4eb" +dependencies = [ + "encode_unicode", + "lazy_static", + "libc", + "unicode-width", + "windows-sys 0.52.0", +] + +[[package]] +name = "const_fn" +version = "0.4.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fbdcdcb6d86f71c5e97409ad45898af11cbc995b4ee8112d59095a28d376c935" + +[[package]] +name = "constant_time_eq" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "245097e9a4535ee1e3e3931fcfcd55a796a44c643e8596ff6566d68f09b87bbc" + +[[package]] +name = "constant_time_eq" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f7144d30dcf0fafbce74250a3963025d8d52177934239851c917d29f1df280c2" + +[[package]] +name = "convert_case" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6245d59a3e82a7fc217c5828a6692dbc6dfb63a0c8c90495621f7b9d79704a0e" + +[[package]] +name = "cookie" +version = "0.15.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc6e25dfc584d06a3dbf775d207ff00d7de98d824c952dd2233dfbb261889a42" +dependencies = [ + "time 0.2.27", + "version_check", +] + +[[package]] +name = "cookie" +version = "0.16.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e859cd57d0710d9e06c381b550c06e76992472a8c6d527aecd2fc673dcc231fb" +dependencies = [ + "percent-encoding", + "time 0.3.34", + "version_check", +] + +[[package]] +name = "core-foundation" +version = "0.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "91e195e091a93c46f7102ec7818a2aa394e1e1771c3ab4825963fa03e45afb8f" +dependencies = [ + "core-foundation-sys", + "libc", +] + +[[package]] +name = "core-foundation-sys" +version = "0.8.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "06ea2b9bc92be3c2baa9334a323ebca2d6f074ff852cd1d7b11064035cd3868f" + +[[package]] +name = "cpufeatures" +version = "0.2.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "53fe5e26ff1b7aef8bca9c6080520cfb8d9333c7568e1829cef191a9723e5504" +dependencies = [ + "libc", +] + +[[package]] +name = "crc32fast" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b3855a8a784b474f333699ef2bbca9db2c4a1f6d9088a90a2d25b1eb53111eaa" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "crossbeam-channel" +version = "0.5.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ab3db02a9c5b5121e1e42fbdb1aeb65f5e02624cc58c43f2884c6ccac0b82f95" +dependencies = [ + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-deque" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "613f8cc01fe9cf1a3eb3d7f488fd2fa8388403e97039e2f73692932e291a770d" +dependencies = [ + "crossbeam-epoch", + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-epoch" +version = "0.9.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b82ac4a3c2ca9c3460964f020e1402edd5753411d7737aa39c3714ad1b5420e" +dependencies = [ + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-utils" +version = "0.8.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "248e3bacc7dc6baa3b21e405ee045c3047101a49145e7e9eca583ab4c2ca5345" + +[[package]] +name = "crunchy" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a81dae078cea95a014a339291cec439d2f232ebe854a9d672b796c6afafa9b7" + +[[package]] +name = "crypto-common" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" +dependencies = [ + "generic-array", + "typenum", +] + +[[package]] +name = "darling" +version = "0.20.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "54e36fcd13ed84ffdfda6f5be89b31287cbb80c439841fe69e04841435464391" +dependencies = [ + "darling_core", + "darling_macro", +] + +[[package]] +name = "darling_core" +version = "0.20.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c2cf1c23a687a1feeb728783b993c4e1ad83d99f351801977dd809b48d0a70f" +dependencies = [ + "fnv", + "ident_case", + "proc-macro2", + "quote", + "strsim 0.10.0", + "syn 2.0.52", +] + +[[package]] +name = "darling_macro" +version = "0.20.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a668eda54683121533a393014d8692171709ff57a7d61f187b6e782719f8933f" +dependencies = [ + "darling_core", + "quote", + "syn 2.0.52", +] + +[[package]] +name = "data-encoding" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7e962a19be5cfc3f3bf6dd8f61eb50107f356ad6270fbb3ed41476571db78be5" + +[[package]] +name = "debugid" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bef552e6f588e446098f6ba40d89ac146c8c7b64aade83c051ee00bb5d2bc18d" +dependencies = [ + "serde", + "uuid", +] + +[[package]] +name = "deranged" +version = "0.3.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b42b6fa04a440b495c8b04d0e71b707c585f83cb9cb28cf8cd0d976c315e31b4" +dependencies = [ + "powerfmt", + "serde", +] + +[[package]] +name = "derivative" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fcc3dd5e9e9c0b295d6e1e4d811fb6f157d5ffd784b8d202fc62eac8035a770b" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "derive_more" +version = "0.99.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4fb810d30a7c1953f91334de7244731fc3f3c10d7fe163338a35b9f640960321" +dependencies = [ + "convert_case", + "proc-macro2", + "quote", + "rustc_version 0.4.0", + "syn 1.0.109", +] + +[[package]] +name = "dialoguer" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "658bce805d770f407bc62102fca7c2c64ceef2fbcb2b8bd19d2765ce093980de" +dependencies = [ + "console", + "shell-words", + "tempfile", + "thiserror", + "zeroize", +] + +[[package]] +name = "digest" +version = "0.10.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" +dependencies = [ + "block-buffer", + "crypto-common", + "subtle", +] + +[[package]] +name = "directories" +version = "5.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a49173b84e034382284f27f1af4dcbbd231ffa358c0fe316541a7337f376a35" +dependencies = [ + "dirs-sys", +] + +[[package]] +name = "dirs" +version = "1.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3fd78930633bd1c6e35c4b42b1df7b0cbc6bc191146e512bb3bedf243fcc3901" +dependencies = [ + "libc", + "redox_users 0.3.5", + "winapi", +] + +[[package]] +name = "dirs" +version = "5.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "44c45a9d03d6676652bcb5e724c7e988de1acad23a711b5217ab9cbecbec2225" +dependencies = [ + "dirs-sys", +] + +[[package]] +name = "dirs-sys" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "520f05a5cbd335fae5a99ff7a6ab8627577660ee5cfd6a94a6a929b52ff0321c" +dependencies = [ + "libc", + "option-ext", + "redox_users 0.4.4", + "windows-sys 0.48.0", +] + +[[package]] +name = "discard" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "212d0f5754cb6769937f4501cc0e67f4f4483c8d2c3e1e922ee9edbe4ab4c7c0" + +[[package]] +name = "dotenvy" +version = "0.15.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1aaf95b3e5c8f23aa320147307562d361db0ae0d51242340f558153b4eb2439b" + +[[package]] +name = "downcast-rs" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ea835d29036a4087793836fa931b08837ad5e957da9e23886b29586fb9b6650" + +[[package]] +name = "dunce" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "56ce8c6da7551ec6c462cbaf3bfbc75131ebbfa1c944aeaa9dab51ca1c5f0c3b" + +[[package]] +name = "either" +version = "1.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "11157ac094ffbdde99aa67b23417ebdd801842852b500e395a45a9c0aac03e4a" + +[[package]] +name = "encode_unicode" +version = "0.3.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a357d28ed41a50f9c765dbfe56cbc04a64e53e5fc58ba79fbc34c10ef3df831f" + +[[package]] +name = "encoding_rs" +version = "0.8.33" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7268b386296a025e474d5140678f75d6de9493ae55a5d709eeb9dd08149945e1" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "endian-type" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c34f04666d835ff5d62e058c3995147c06f42fe86ff053337632bca83e42702d" + +[[package]] +name = "enumflags2" +version = "0.7.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3278c9d5fb675e0a51dabcf4c0d355f692b064171535ba72361be1528a9d8e8d" +dependencies = [ + "enumflags2_derive", + "serde", +] + +[[package]] +name = "enumflags2_derive" +version = "0.7.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c785274071b1b420972453b306eeca06acf4633829db4223b58a2a8c5953bc4" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.52", +] + +[[package]] +name = "env_logger" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4cd405aab171cb85d6735e5c8d9db038c17d3ca007a4d2c25f337935c3d90580" +dependencies = [ + "humantime", + "is-terminal", + "log", + "regex", + "termcolor", +] + +[[package]] +name = "equivalent" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" + +[[package]] +name = "erased-serde" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "388979d208a049ffdfb22fa33b9c81942215b940910bccfe258caeb25d125cb3" +dependencies = [ + "serde", +] + +[[package]] +name = "errno" +version = "0.3.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a258e46cdc063eb8519c00b9fc845fc47bcfca4130e2f08e88665ceda8474245" +dependencies = [ + "libc", + "windows-sys 0.52.0", +] + +[[package]] +name = "error-code" +version = "3.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a0474425d51df81997e2f90a21591180b38eccf27292d755f3e30750225c175b" + +[[package]] +name = "event-listener" +version = "2.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0206175f82b8d6bf6652ff7d71a1e27fd2e4efde587fd368662814d6ec1d9ce0" + +[[package]] +name = "event-listener" +version = "3.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d93877bcde0eb80ca09131a08d23f0a5c18a620b01db137dba666d18cd9b30c2" +dependencies = [ + "concurrent-queue", + "parking", + "pin-project-lite", +] + +[[package]] +name = "event-listener" +version = "4.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67b215c49b2b248c855fb73579eb1f4f26c38ffdc12973e20e07b91d78d5646e" +dependencies = [ + "concurrent-queue", + "parking", + "pin-project-lite", +] + +[[package]] +name = "event-listener" +version = "5.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b5fb89194fa3cad959b833185b3063ba881dbfc7030680b314250779fb4cc91" +dependencies = [ + "concurrent-queue", + "parking", + "pin-project-lite", +] + +[[package]] +name = "event-listener-strategy" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "958e4d70b6d5e81971bebec42271ec641e7ff4e170a6fa605f2b8a8b65cb97d3" +dependencies = [ + "event-listener 4.0.3", + "pin-project-lite", +] + +[[package]] +name = "event-listener-strategy" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "feedafcaa9b749175d5ac357452a9d41ea2911da598fde46ce1fe02c37751291" +dependencies = [ + "event-listener 5.2.0", + "pin-project-lite", +] + +[[package]] +name = "fastdivide" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "25c7df09945d65ea8d70b3321547ed414bbc540aad5bac6883d021b970f35b04" + +[[package]] +name = "fastrand" +version = "1.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e51093e27b0797c359783294ca4f0a911c270184cb10f85783b118614a1501be" +dependencies = [ + "instant", +] + +[[package]] +name = "fastrand" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "25cbce373ec4653f1a01a31e8a5e5ec0c622dc27ff9c4e6606eefef5cbbed4a5" + +[[package]] +name = "fd-lock" +version = "4.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7e5768da2206272c81ef0b5e951a41862938a6070da63bcea197899942d3b947" +dependencies = [ + "cfg-if", + "rustix 0.38.31", + "windows-sys 0.52.0", +] + +[[package]] +name = "filetime" +version = "0.2.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ee447700ac8aa0b2f2bd7bc4462ad686ba06baa6727ac149a2d6277f0d240fd" +dependencies = [ + "cfg-if", + "libc", + "redox_syscall 0.4.1", + "windows-sys 0.52.0", +] + +[[package]] +name = "findshlibs" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "40b9e59cd0f7e0806cca4be089683ecb6434e602038df21fe6bf6711b2f07f64" +dependencies = [ + "cc", + "lazy_static", + "libc", + "winapi", +] + +[[package]] +name = "flate2" +version = "1.0.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "46303f565772937ffe1d394a4fac6f411c6013172fadde9dcdb1e147a086940e" +dependencies = [ + "crc32fast", + "miniz_oxide", +] + +[[package]] +name = "fnv" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" + +[[package]] +name = "foreign-types" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1" +dependencies = [ + "foreign-types-shared", +] + +[[package]] +name = "foreign-types-shared" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" + +[[package]] +name = "form_urlencoded" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e13624c2627564efccf4934284bdd98cbaa14e79b0b5a141218e507b3a823456" +dependencies = [ + "percent-encoding", +] + +[[package]] +name = "fs4" +version = "0.6.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2eeb4ed9e12f43b7fa0baae3f9cdda28352770132ef2e09a23760c29cae8bd47" +dependencies = [ + "rustix 0.38.31", + "windows-sys 0.48.0", +] + +[[package]] +name = "full_moon" +version = "0.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "24ef4f8ad0689d3a86bb483650422d72e6f79a37fdc83ed5426cafe96b776ce1" +dependencies = [ + "bytecount", + "cfg-if", + "derive_more", + "full_moon_derive", + "logos", + "paste", + "serde", + "smol_str", + "stacker", +] + +[[package]] +name = "full_moon_derive" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "99b4bd12ce56927d1dc5478d21528ea8c4b93ca85ff8f8043b6a5351a2a3c6f7" +dependencies = [ + "indexmap 1.9.3", + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "futures-channel" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eac8f7d7865dcb88bd4373ab671c8cf4508703796caa2b1985a9ca867b3fcb78" +dependencies = [ + "futures-core", +] + +[[package]] +name = "futures-core" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dfc6580bb841c5a68e9ef15c77ccc837b40a7504914d52e47b8b0e9bbda25a1d" + +[[package]] +name = "futures-executor" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a576fc72ae164fca6b9db127eaa9a9dda0d61316034f33a0a0d4eda41f02b01d" +dependencies = [ + "futures-core", + "futures-task", + "futures-util", +] + +[[package]] +name = "futures-io" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a44623e20b9681a318efdd71c299b6b222ed6f231972bfe2f224ebad6311f0c1" + +[[package]] +name = "futures-lite" +version = "1.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49a9d51ce47660b1e808d3c990b4709f2f415d928835a17dfd16991515c46bce" +dependencies = [ + "fastrand 1.9.0", + "futures-core", + "futures-io", + "memchr", + "parking", + "pin-project-lite", + "waker-fn", +] + +[[package]] +name = "futures-lite" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "445ba825b27408685aaecefd65178908c36c6e96aaf6d8599419d46e624192ba" +dependencies = [ + "fastrand 2.0.1", + "futures-core", + "futures-io", + "parking", + "pin-project-lite", +] + +[[package]] +name = "futures-macro" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.52", +] + +[[package]] +name = "futures-sink" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9fb8e00e87438d937621c1c6269e53f536c14d3fbd6a042bb24879e57d474fb5" + +[[package]] +name = "futures-task" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38d84fa142264698cdce1a9f9172cf383a0c82de1bddcf3092901442c4097004" + +[[package]] +name = "futures-util" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d6401deb83407ab3da39eba7e33987a73c3df0c82b4bb5813ee871c19c41d48" +dependencies = [ + "futures-core", + "futures-io", + "futures-macro", + "futures-sink", + "futures-task", + "memchr", + "pin-project-lite", + "pin-utils", + "slab", +] + +[[package]] +name = "generator" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b5b25e5b3e733153bcab35ee4671b46604b42516163cae442d1601cb716f2ac5" +dependencies = [ + "cc", + "cfg-if", + "libc", + "log", + "rustversion", + "windows", +] + +[[package]] +name = "generic-array" +version = "0.14.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" +dependencies = [ + "typenum", + "version_check", +] + +[[package]] +name = "getrandom" +version = "0.1.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8fc3cb4d91f53b50155bdcfd23f6a4c39ae1969c2ae85982b135750cccaf5fce" +dependencies = [ + "cfg-if", + "libc", + "wasi 0.9.0+wasi-snapshot-preview1", +] + +[[package]] +name = "getrandom" +version = "0.2.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "190092ea657667030ac6a35e305e62fc4dd69fd98ac98631e5d3a2b1575a12b5" +dependencies = [ + "cfg-if", + "libc", + "wasi 0.11.0+wasi-snapshot-preview1", +] + +[[package]] +name = "gimli" +version = "0.28.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4271d37baee1b8c7e4b708028c57d816cf9d2434acb33a549475f78c181f6253" + +[[package]] +name = "git2" +version = "0.18.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b3ba52851e73b46a4c3df1d89343741112003f0f6f13beb0dfac9e457c3fdcd" +dependencies = [ + "bitflags 2.4.2", + "libc", + "libgit2-sys", + "log", + "openssl-probe", + "openssl-sys", + "url", +] + +[[package]] +name = "glam" +version = "0.25.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "151665d9be52f9bb40fc7966565d39666f2d1e69233571b71b87791c7e0528b3" + +[[package]] +name = "glob" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b" + +[[package]] +name = "globset" +version = "0.4.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "57da3b9b5b85bd66f31093f8c408b90a74431672542466497dcbdfdc02034be1" +dependencies = [ + "aho-corasick", + "bstr", + "log", + "regex-automata 0.4.5", + "regex-syntax 0.8.2", +] + +[[package]] +name = "h2" +version = "0.3.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bb2c4422095b67ee78da96fbb51a4cc413b3b25883c7717ff7ca1ab31022c9c9" +dependencies = [ + "bytes", + "fnv", + "futures-core", + "futures-sink", + "futures-util", + "http", + "indexmap 2.2.5", + "slab", + "tokio", + "tokio-util", + "tracing", +] + +[[package]] +name = "hashbrown" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" + +[[package]] +name = "hashbrown" +version = "0.14.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "290f1a1d9242c78d09ce40a5e87e7554ee637af1351968159f4952f028f75604" +dependencies = [ + "ahash", + "allocator-api2", +] + +[[package]] +name = "heck" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" + +[[package]] +name = "hermit-abi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024" + +[[package]] +name = "hex" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" + +[[package]] +name = "hkdf" +version = "0.12.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7b5f8eb2ad728638ea2c7d47a21db23b7b58a72ed6a38256b8a1849f15fbbdf7" +dependencies = [ + "hmac", +] + +[[package]] +name = "hmac" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c49c37c09c17a53d937dfbb742eb3a961d65a994e6bcdcf37e7399d0cc8ab5e" +dependencies = [ + "digest", +] + +[[package]] +name = "home" +version = "0.5.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3d1354bf6b7235cb4a0576c2619fd4ed18183f689b12b006a0ee7329eeff9a5" +dependencies = [ + "windows-sys 0.52.0", +] + +[[package]] +name = "hostname" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c731c3e10504cc8ed35cfe2f1db4c9274c3d35fa486e3b31df46f068ef3e867" +dependencies = [ + "libc", + "match_cfg", + "winapi", +] + +[[package]] +name = "htmlescape" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e9025058dae765dee5070ec375f591e2ba14638c63feff74f13805a72e523163" + +[[package]] +name = "http" +version = "0.2.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8947b1a6fad4393052c7ba1f4cd97bed3e953a95c79c92ad9b051a04611d9fbb" +dependencies = [ + "bytes", + "fnv", + "itoa", +] + +[[package]] +name = "http-body" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7ceab25649e9960c0311ea418d17bee82c0dcec1bd053b5f9a66e265a693bed2" +dependencies = [ + "bytes", + "http", + "pin-project-lite", +] + +[[package]] +name = "httparse" +version = "1.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d897f394bad6a705d5f4104762e116a75639e470d80901eed05a860a95cb1904" + +[[package]] +name = "httpdate" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9" + +[[package]] +name = "humantime" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4" + +[[package]] +name = "hyper" +version = "0.14.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bf96e135eb83a2a8ddf766e426a841d8ddd7449d5f00d34ea02b41d2f19eef80" +dependencies = [ + "bytes", + "futures-channel", + "futures-core", + "futures-util", + "h2", + "http", + "http-body", + "httparse", + "httpdate", + "itoa", + "pin-project-lite", + "socket2 0.5.6", + "tokio", + "tower-service", + "tracing", + "want", +] + +[[package]] +name = "hyper-rustls" +version = "0.24.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec3efd23720e2049821a693cbc7e65ea87c72f1c58ff2f9522ff332b1491e590" +dependencies = [ + "futures-util", + "http", + "hyper", + "rustls", + "tokio", + "tokio-rustls", +] + +[[package]] +name = "hyper-tls" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d6183ddfa99b85da61a140bea0efc93fdf56ceaa041b37d553518030827f9905" +dependencies = [ + "bytes", + "hyper", + "native-tls", + "tokio", + "tokio-native-tls", +] + +[[package]] +name = "hyper-tungstenite" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7cc7dcb1ab67cd336f468a12491765672e61a3b6b148634dbfe2fe8acd3fe7d9" +dependencies = [ + "hyper", + "pin-project-lite", + "tokio", + "tokio-tungstenite", + "tungstenite", +] + +[[package]] +name = "iana-time-zone" +version = "0.1.60" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e7ffbb5a1b541ea2561f8c41c087286cc091e21e556a4f09a8f6cbf17b69b141" +dependencies = [ + "android_system_properties", + "core-foundation-sys", + "iana-time-zone-haiku", + "js-sys", + "wasm-bindgen", + "windows-core 0.52.0", +] + +[[package]] +name = "iana-time-zone-haiku" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f31827a206f56af32e590ba56d5d2d085f558508192593743f16b2306495269f" +dependencies = [ + "cc", +] + +[[package]] +name = "ident_case" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" + +[[package]] +name = "idna" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "634d9b1461af396cad843f47fdba5597a4f9e6ddd4bfb6ff5d85028c25cb12f6" +dependencies = [ + "unicode-bidi", + "unicode-normalization", +] + +[[package]] +name = "ignore" +version = "0.4.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b46810df39e66e925525d6e38ce1e7f6e1d208f72dc39757880fcb66e2c58af1" +dependencies = [ + "crossbeam-deque", + "globset", + "log", + "memchr", + "regex-automata 0.4.5", + "same-file", + "walkdir", + "winapi-util", +] + +[[package]] +name = "include_dir" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "18762faeff7122e89e0857b02f7ce6fcc0d101d5e9ad2ad7846cc01d61b7f19e" +dependencies = [ + "glob", + "include_dir_macros", +] + +[[package]] +name = "include_dir_macros" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b139284b5cf57ecfa712bcc66950bb635b31aff41c188e8a4cfc758eca374a3f" +dependencies = [ + "proc-macro2", + "quote", +] + +[[package]] +name = "indexmap" +version = "1.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99" +dependencies = [ + "autocfg", + "hashbrown 0.12.3", +] + +[[package]] +name = "indexmap" +version = "2.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7b0b929d511467233429c45a44ac1dcaa21ba0f5ba11e4879e6ed28ddb4f9df4" +dependencies = [ + "equivalent", + "hashbrown 0.14.3", +] + +[[package]] +name = "indicatif" +version = "0.17.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "763a5a8f45087d6bcea4222e7b72c291a054edf80e4ef6efd2a4979878c7bea3" +dependencies = [ + "console", + "instant", + "number_prefix", + "portable-atomic", + "unicode-width", +] + +[[package]] +name = "indicatif-log-bridge" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2963046f28a204e3e3fd7e754fd90a6235da05b5378f24707ff0ec9513725ce3" +dependencies = [ + "indicatif", + "log", +] + +[[package]] +name = "instant" +version = "0.1.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a5bbe824c507c5da5956355e86a746d82e0e1464f65d862cc5e71da70e94b2c" +dependencies = [ + "cfg-if", + "js-sys", + "wasm-bindgen", + "web-sys", +] + +[[package]] +name = "io-lifetimes" +version = "1.0.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eae7b9aee968036d54dce06cebaefd919e4472e753296daccd6d344e3e2df0c2" +dependencies = [ + "hermit-abi", + "libc", + "windows-sys 0.48.0", +] + +[[package]] +name = "ipnet" +version = "2.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f518f335dce6725a761382244631d86cf0ccb2863413590b31338feb467f9c3" + +[[package]] +name = "is-terminal" +version = "0.4.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f23ff5ef2b80d608d61efee834934d862cd92461afc0560dedf493e4c033738b" +dependencies = [ + "hermit-abi", + "libc", + "windows-sys 0.52.0", +] + +[[package]] +name = "itertools" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1c173a5686ce8bfa551b3563d0c2170bf24ca44da99c7ca4bfdab5418c3fe57" +dependencies = [ + "either", +] + +[[package]] +name = "itertools" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba291022dbbd398a455acf126c1e341954079855bc60dfdda641363bd6922569" +dependencies = [ + "either", +] + +[[package]] +name = "itoa" +version = "1.0.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1a46d1a171d865aa5f83f92695765caa047a9b4cbae2cbf37dbd613a793fd4c" + +[[package]] +name = "jobserver" +version = "0.1.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ab46a6e9526ddef3ae7f787c06f0f2600639ba80ea3eade3d8e670a2230f51d6" +dependencies = [ + "libc", +] + +[[package]] +name = "js-sys" +version = "0.3.68" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "406cda4b368d531c842222cf9d2600a9a4acce8d29423695379c6868a143a9ee" +dependencies = [ + "wasm-bindgen", +] + +[[package]] +name = "keyring" +version = "2.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1be8bc4c6b6e9d85ecdad090fcf342a9216f53d747a537cc05e3452fd650ca46" +dependencies = [ + "byteorder 1.5.0", + "lazy_static", + "linux-keyutils", + "secret-service", + "security-framework", + "windows-sys 0.52.0", +] + +[[package]] +name = "language-tags" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d4345964bb142484797b161f473a503a434de77149dd8c7427788c6e13379388" + +[[package]] +name = "lazy_static" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" + +[[package]] +name = "levenshtein_automata" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c2cdeb66e45e9f36bfad5bbdb4d2384e70936afbee843c6f6543f0c551ebb25" + +[[package]] +name = "libc" +version = "0.2.153" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c198f91728a82281a64e1f4f9eeb25d82cb32a5de251c6bd1b5154d63a8e7bd" + +[[package]] +name = "libgit2-sys" +version = "0.16.2+1.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee4126d8b4ee5c9d9ea891dd875cfdc1e9d0950437179104b183d7d8a74d24e8" +dependencies = [ + "cc", + "libc", + "libssh2-sys", + "libz-sys", + "openssl-sys", + "pkg-config", +] + +[[package]] +name = "libloading" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2caa5afb8bf9f3a2652760ce7d4f62d21c4d5a423e68466fca30df82f2330164" +dependencies = [ + "cfg-if", + "windows-targets 0.52.4", +] + +[[package]] +name = "libredox" +version = "0.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85c833ca1e66078851dba29046874e38f08b2c883700aa29a03ddd3b23814ee8" +dependencies = [ + "bitflags 2.4.2", + "libc", + "redox_syscall 0.4.1", +] + +[[package]] +name = "libssh2-sys" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2dc8a030b787e2119a731f1951d6a773e2280c660f8ec4b0f5e1505a386e71ee" +dependencies = [ + "cc", + "libc", + "libz-sys", + "openssl-sys", + "pkg-config", + "vcpkg", +] + +[[package]] +name = "libz-sys" +version = "1.1.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "037731f5d3aaa87a5675e895b63ddff1a87624bc29f77004ea829809654e48f6" +dependencies = [ + "cc", + "libc", + "pkg-config", + "vcpkg", +] + +[[package]] +name = "line-wrap" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f30344350a2a51da54c1d53be93fade8a237e545dbcc4bdbe635413f2117cab9" +dependencies = [ + "safemem", +] + +[[package]] +name = "linux-keyutils" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "761e49ec5fd8a5a463f9b84e877c373d888935b71c6be78f3767fe2ae6bed18e" +dependencies = [ + "bitflags 2.4.2", + "libc", +] + +[[package]] +name = "linux-raw-sys" +version = "0.3.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ef53942eb7bf7ff43a617b3e2c1c4a5ecf5944a7c1bc12d7ee39bbb15e5c1519" + +[[package]] +name = "linux-raw-sys" +version = "0.4.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "01cda141df6706de531b6c46c3a33ecca755538219bd484262fa09410c13539c" + +[[package]] +name = "local-channel" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6cbc85e69b8df4b8bb8b89ec634e7189099cea8927a276b7384ce5488e53ec8" +dependencies = [ + "futures-core", + "futures-sink", + "local-waker", +] + +[[package]] +name = "local-waker" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4d873d7c67ce09b42110d801813efbc9364414e356be9935700d368351657487" + +[[package]] +name = "lock_api" +version = "0.4.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c168f8615b12bc01f9c17e2eb0cc07dcae1940121185446edc3744920e8ef45" +dependencies = [ + "autocfg", + "scopeguard", +] + +[[package]] +name = "log" +version = "0.4.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "90ed8c1e510134f979dbc4f070f87d4313098b704861a105fe34231c70a3901c" + +[[package]] +name = "logos" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bf8b031682c67a8e3d5446840f9573eb7fe26efe7ec8d195c9ac4c0647c502f1" +dependencies = [ + "logos-derive", +] + +[[package]] +name = "logos-derive" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1d849148dbaf9661a6151d1ca82b13bb4c4c128146a88d05253b38d4e2f496c" +dependencies = [ + "beef", + "fnv", + "proc-macro2", + "quote", + "regex-syntax 0.6.29", + "syn 1.0.109", +] + +[[package]] +name = "loom" +version = "0.5.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ff50ecb28bb86013e935fb6683ab1f6d3a20016f123c76fd4c27470076ac30f5" +dependencies = [ + "cfg-if", + "generator", + "pin-utils", + "scoped-tls", + "tracing", + "tracing-subscriber", +] + +[[package]] +name = "lru" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4a83fb7698b3643a0e34f9ae6f2e8f0178c0fd42f8b59d493aa271ff3a5bf21" +dependencies = [ + "hashbrown 0.14.3", +] + +[[package]] +name = "luau0-src" +version = "0.8.3+luau614" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4d0dc9f950d074893d18af156124f8296e7477f96dfbdc0520fb8df5a8aa3898" +dependencies = [ + "cc", +] + +[[package]] +name = "lune" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5bcc079b3fb923a1e21c6c4ec0ff879636b85ae566f6370fc7f9a603749ca573" +dependencies = [ + "anyhow", + "async-compression", + "async-trait", + "chrono", + "chrono_lc", + "clap", + "console", + "dialoguer", + "directories", + "dunce", + "env_logger", + "futures-util", + "glam", + "hyper", + "hyper-tungstenite", + "include_dir", + "itertools 0.12.1", + "lz4_flex", + "mlua", + "once_cell", + "os_str_bytes", + "path-clean", + "pathdiff", + "pin-project", + "rand", + "rbx_binary", + "rbx_cookie", + "rbx_dom_weak", + "rbx_reflection", + "rbx_reflection_database", + "rbx_xml", + "regex", + "reqwest", + "rustyline", + "serde", + "serde_json", + "serde_yaml", + "thiserror", + "tokio", + "tokio-tungstenite", + "toml", + "tracing", + "tracing-subscriber", + "urlencoding", +] + +[[package]] +name = "lz4" +version = "1.24.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7e9e2dd86df36ce760a60f6ff6ad526f7ba1f14ba0356f8254fb6905e6494df1" +dependencies = [ + "libc", + "lz4-sys", +] + +[[package]] +name = "lz4-sys" +version = "1.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "57d27b317e207b10f69f5e75494119e391a96f48861ae870d1da6edac98ca900" +dependencies = [ + "cc", + "libc", +] + +[[package]] +name = "lz4_flex" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "912b45c753ff5f7f5208307e8ace7d2a2e30d024e26d3509f3dce546c044ce15" +dependencies = [ + "twox-hash", +] + +[[package]] +name = "match_cfg" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ffbee8634e0d45d258acb448e7eaab3fce7a0a467395d4d9f228e3c1f01fb2e4" + +[[package]] +name = "matchers" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8263075bb86c5a1b1427b5ae862e8889656f126e9f77c484496e8b47cf5c5558" +dependencies = [ + "regex-automata 0.1.10", +] + +[[package]] +name = "md-5" +version = "0.10.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d89e7ee0cfbedfc4da3340218492196241d89eefb6dab27de5df917a6d2e78cf" +dependencies = [ + "cfg-if", + "digest", +] + +[[package]] +name = "measure_time" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "56220900f1a0923789ecd6bf25fbae8af3b2f1ff3e9e297fc9b6b8674dd4d852" +dependencies = [ + "instant", + "log", +] + +[[package]] +name = "memchr" +version = "2.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "523dc4f511e55ab87b694dc30d0f820d60906ef06413f93d4d7a1385599cc149" + +[[package]] +name = "memmap2" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f49388d20533534cd19360ad3d6a7dadc885944aa802ba3995040c5ec11288c6" +dependencies = [ + "libc", +] + +[[package]] +name = "memoffset" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5de893c32cde5f383baa4c04c5d6dbdd735cfd4a794b0debdb2bb1b421da5ff4" +dependencies = [ + "autocfg", +] + +[[package]] +name = "memoffset" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a634b1c61a95585bd15607c6ab0c4e5b226e695ff2800ba0cdccddf208c406c" +dependencies = [ + "autocfg", +] + +[[package]] +name = "mime" +version = "0.3.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a" + +[[package]] +name = "mime_guess" +version = "2.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4192263c238a5f0d0c6bfd21f336a313a4ce1c450542449ca191bb657b4642ef" +dependencies = [ + "mime", + "unicase", +] + +[[package]] +name = "minimal-lexical" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" + +[[package]] +name = "miniz_oxide" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d811f3e15f28568be3407c8e7fdb6514c1cda3cb30683f15b6a1a1dc4ea14a7" +dependencies = [ + "adler", +] + +[[package]] +name = "mio" +version = "0.8.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4a650543ca06a924e8b371db273b2756685faae30f8487da1b56505a8f78b0c" +dependencies = [ + "libc", + "log", + "wasi 0.11.0+wasi-snapshot-preview1", + "windows-sys 0.48.0", +] + +[[package]] +name = "mlua" +version = "0.9.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "868d02cb5eb97761bbf6bd6922c1c7a88b8ea252bbf43bd8350a0bf8497a1fc0" +dependencies = [ + "bstr", + "erased-serde", + "libloading", + "mlua-sys", + "num-traits", + "once_cell", + "rustc-hash", + "serde", + "serde-value", +] + +[[package]] +name = "mlua-sys" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2847b42764435201d8cbee1f517edb79c4cca4181877b90047587c89e1b7bce4" +dependencies = [ + "cc", + "cfg-if", + "luau0-src", + "pkg-config", +] + +[[package]] +name = "murmurhash32" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2195bf6aa996a481483b29d62a7663eed3fe39600c460e323f8ff41e90bdd89b" + +[[package]] +name = "native-tls" +version = "0.2.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "07226173c32f2926027b63cce4bcd8076c3552846cbe7925f3aaffeac0a3b92e" +dependencies = [ + "lazy_static", + "libc", + "log", + "openssl", + "openssl-probe", + "openssl-sys", + "schannel", + "security-framework", + "security-framework-sys", + "tempfile", +] + +[[package]] +name = "nibble_vec" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77a5d83df9f36fe23f0c3648c6bbb8b0298bb5f1939c8f2704431371f4b84d43" +dependencies = [ + "smallvec", +] + +[[package]] +name = "nix" +version = "0.26.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "598beaf3cc6fdd9a5dfb1630c2800c7acd31df7aaf0f565796fba2b53ca1af1b" +dependencies = [ + "bitflags 1.3.2", + "cfg-if", + "libc", + "memoffset 0.7.1", +] + +[[package]] +name = "nix" +version = "0.27.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2eb04e9c688eff1c89d72b407f168cf79bb9e867a9d3323ed6c01519eb9cc053" +dependencies = [ + "bitflags 2.4.2", + "cfg-if", + "libc", +] + +[[package]] +name = "nom" +version = "7.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a" +dependencies = [ + "memchr", + "minimal-lexical", +] + +[[package]] +name = "nu-ansi-term" +version = "0.46.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77a8165726e8236064dbb45459242600304b42a5ea24ee2948e18e023bf7ba84" +dependencies = [ + "overload", + "winapi", +] + +[[package]] +name = "num" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b05180d69e3da0e530ba2a1dae5110317e49e3b7f3d41be227dc5f92e49ee7af" +dependencies = [ + "num-bigint", + "num-complex", + "num-integer", + "num-iter", + "num-rational", + "num-traits", +] + +[[package]] +name = "num-bigint" +version = "0.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "608e7659b5c3d7cba262d894801b9ec9d00de989e8a82bd4bef91d08da45cdc0" +dependencies = [ + "autocfg", + "num-integer", + "num-traits", +] + +[[package]] +name = "num-complex" +version = "0.4.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "23c6602fda94a57c990fe0df199a035d83576b496aa29f4e634a8ac6004e68a6" +dependencies = [ + "num-traits", +] + +[[package]] +name = "num-conv" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "51d515d32fb182ee37cda2ccdcb92950d6a3c2893aa280e540671c2cd0f3b1d9" + +[[package]] +name = "num-integer" +version = "0.1.46" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7969661fd2958a5cb096e56c8e1ad0444ac2bbcd0061bd28660485a44879858f" +dependencies = [ + "num-traits", +] + +[[package]] +name = "num-iter" +version = "0.1.44" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d869c01cc0c455284163fd0092f1f93835385ccab5a98a0dcc497b2f8bf055a9" +dependencies = [ + "autocfg", + "num-integer", + "num-traits", +] + +[[package]] +name = "num-rational" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0638a1c9d0a3c0914158145bc76cff373a75a627e6ecbfb71cbe6f453a5a19b0" +dependencies = [ + "autocfg", + "num-bigint", + "num-integer", + "num-traits", +] + +[[package]] +name = "num-traits" +version = "0.2.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da0df0e5185db44f69b44f26786fe401b6c293d1907744beaa7fa62b2e5a517a" +dependencies = [ + "autocfg", +] + +[[package]] +name = "num_cpus" +version = "1.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4161fcb6d602d4d2081af7c3a45852d875a03dd337a6bfdd6e06407b61342a43" +dependencies = [ + "hermit-abi", + "libc", +] + +[[package]] +name = "number_prefix" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "830b246a0e5f20af87141b25c173cd1b609bd7779a4617d6ec582abaf90870f3" + +[[package]] +name = "object" +version = "0.32.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a6a622008b6e321afc04970976f62ee297fdbaa6f95318ca343e3eebb9648441" +dependencies = [ + "memchr", +] + +[[package]] +name = "once_cell" +version = "1.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" + +[[package]] +name = "oneshot" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6f6640c6bda7731b1fdbab747981a0f896dd1fedaf9f4a53fa237a04a84431f4" +dependencies = [ + "loom", +] + +[[package]] +name = "opaque-debug" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c08d65885ee38876c4f86fa503fb49d7b507c2b62552df7c70b2fce627e06381" + +[[package]] +name = "openssl" +version = "0.10.63" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "15c9d69dd87a29568d4d017cfe8ec518706046a05184e5aea92d0af890b803c8" +dependencies = [ + "bitflags 2.4.2", + "cfg-if", + "foreign-types", + "libc", + "once_cell", + "openssl-macros", + "openssl-sys", +] + +[[package]] +name = "openssl-macros" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.52", +] + +[[package]] +name = "openssl-probe" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf" + +[[package]] +name = "openssl-sys" +version = "0.9.99" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "22e1bf214306098e4832460f797824c05d25aacdf896f64a985fb0fd992454ae" +dependencies = [ + "cc", + "libc", + "pkg-config", + "vcpkg", +] + +[[package]] +name = "option-ext" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "04744f49eae99ab78e0d5c0b603ab218f515ea8cfe5a456d7629ad883a3b6e7d" + +[[package]] +name = "ordered-float" +version = "2.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68f19d67e5a2795c94e73e0bb1cc1a7edeb2e28efd39e2e1c9b7a40c1108b11c" +dependencies = [ + "num-traits", +] + +[[package]] +name = "ordered-stream" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9aa2b01e1d916879f73a53d01d1d6cee68adbb31d6d9177a8cfce093cced1d50" +dependencies = [ + "futures-core", + "pin-project-lite", +] + +[[package]] +name = "os_info" +version = "3.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "006e42d5b888366f1880eda20371fedde764ed2213dc8496f49622fa0c99cd5e" +dependencies = [ + "log", + "serde", + "winapi", +] + +[[package]] +name = "os_str_bytes" +version = "6.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2355d85b9a3786f481747ced0e0ff2ba35213a1f9bd406ed906554d7af805a1" +dependencies = [ + "memchr", +] + +[[package]] +name = "overload" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b15813163c1d831bf4a13c3610c05c0d03b39feb07f7e09fa234dac9b15aaf39" + +[[package]] +name = "ownedbytes" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6e8a72b918ae8198abb3a18c190288123e1d442b6b9a7d709305fd194688b4b7" +dependencies = [ + "stable_deref_trait", +] + +[[package]] +name = "parking" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bb813b8af86854136c6922af0598d719255ecb2179515e6e7730d468f05c9cae" + +[[package]] +name = "parking_lot" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3742b2c103b9f06bc9fff0a37ff4912935851bee6d36f3c02bcc755bcfec228f" +dependencies = [ + "lock_api", + "parking_lot_core", +] + +[[package]] +name = "parking_lot_core" +version = "0.9.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c42a9226546d68acdd9c0a280d17ce19bfe27a46bf68784e4066115788d008e" +dependencies = [ + "cfg-if", + "libc", + "redox_syscall 0.4.1", + "smallvec", + "windows-targets 0.48.5", +] + +[[package]] +name = "parse-size" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "944553dd59c802559559161f9816429058b869003836120e262e8caec061b7ae" + +[[package]] +name = "paste" +version = "1.0.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "de3145af08024dea9fa9914f381a17b8fc6034dfb00f3a84013f7ff43f29ed4c" + +[[package]] +name = "path-clean" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "17359afc20d7ab31fdb42bb844c8b3bb1dabd7dcf7e68428492da7f16966fcef" + +[[package]] +name = "pathdiff" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8835116a5c179084a830efb3adc117ab007512b535bc1a21c991d3b32a6b44dd" + +[[package]] +name = "percent-encoding" +version = "2.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" + +[[package]] +name = "pesde" +version = "0.1.0" +dependencies = [ + "anyhow", + "auth-git2", + "clap", + "directories", + "flate2", + "full_moon", + "futures-executor", + "git2", + "ignore", + "indicatif", + "indicatif-log-bridge", + "keyring", + "log", + "lune", + "pathdiff", + "pretty_env_logger", + "relative-path", + "reqwest", + "semver 1.0.22", + "serde", + "serde_json", + "serde_yaml", + "tar", + "tempfile", + "thiserror", + "threadpool", +] + +[[package]] +name = "pesde-registry" +version = "0.1.0" +dependencies = [ + "actix-cors", + "actix-multipart", + "actix-multipart-derive", + "actix-web", + "actix-web-httpauth", + "dotenvy", + "flate2", + "git2", + "log", + "pesde", + "pretty_env_logger", + "reqwest", + "rusty-s3", + "semver 1.0.22", + "sentry", + "sentry-actix", + "sentry-log", + "serde", + "serde_json", + "serde_yaml", + "tantivy", + "tar", + "thiserror", +] + +[[package]] +name = "pin-project" +version = "1.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0302c4a0442c456bd56f841aee5c3bfd17967563f6fadc9ceb9f9c23cf3807e0" +dependencies = [ + "pin-project-internal", +] + +[[package]] +name = "pin-project-internal" +version = "1.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "266c042b60c9c76b8d53061e52b2e0d1116abc57cefc8c5cd671619a56ac3690" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.52", +] + +[[package]] +name = "pin-project-lite" +version = "0.2.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8afb450f006bf6385ca15ef45d71d2288452bc3683ce2e2cacc0d18e4be60b58" + +[[package]] +name = "pin-utils" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" + +[[package]] +name = "piper" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "668d31b1c4eba19242f2088b2bf3316b82ca31082a8335764db4e083db7485d4" +dependencies = [ + "atomic-waker", + "fastrand 2.0.1", + "futures-io", +] + +[[package]] +name = "pkg-config" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d231b230927b5e4ad203db57bbcbee2802f6bce620b1e4a9024a07d94e2907ec" + +[[package]] +name = "plist" +version = "1.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e5699cc8a63d1aa2b1ee8e12b9ad70ac790d65788cd36101fa37f87ea46c4cef" +dependencies = [ + "base64 0.21.7", + "indexmap 2.2.5", + "line-wrap", + "quick-xml 0.31.0", + "serde", + "time 0.3.34", +] + +[[package]] +name = "polling" +version = "2.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4b2d323e8ca7996b3e23126511a523f7e62924d93ecd5ae73b333815b0eb3dce" +dependencies = [ + "autocfg", + "bitflags 1.3.2", + "cfg-if", + "concurrent-queue", + "libc", + "log", + "pin-project-lite", + "windows-sys 0.48.0", +] + +[[package]] +name = "polling" +version = "3.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "24f040dee2588b4963afb4e420540439d126f73fdacf4a9c486a96d840bac3c9" +dependencies = [ + "cfg-if", + "concurrent-queue", + "pin-project-lite", + "rustix 0.38.31", + "tracing", + "windows-sys 0.52.0", +] + +[[package]] +name = "portable-atomic" +version = "1.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7170ef9988bc169ba16dd36a7fa041e5c4cbeb6a35b76d4c03daded371eae7c0" + +[[package]] +name = "powerfmt" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391" + +[[package]] +name = "ppv-lite86" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" + +[[package]] +name = "pretty_env_logger" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "865724d4dbe39d9f3dd3b52b88d859d66bcb2d6a0acfd5ea68a65fb66d4bdc1c" +dependencies = [ + "env_logger", + "log", +] + +[[package]] +name = "proc-macro-crate" +version = "1.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f4c021e1093a56626774e81216a4ce732a735e5bad4868a03f3ed65ca0c3919" +dependencies = [ + "once_cell", + "toml_edit 0.19.15", +] + +[[package]] +name = "proc-macro-hack" +version = "0.5.20+deprecated" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc375e1527247fe1a97d8b7156678dfe7c1af2fc075c9a4db3690ecd2a148068" + +[[package]] +name = "proc-macro2" +version = "1.0.78" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2422ad645d89c99f8f3e6b88a9fdeca7fabeac836b1002371c4367c8f984aae" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "profiling" +version = "1.0.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "43d84d1d7a6ac92673717f9f6d1518374ef257669c24ebc5ac25d5033828be58" +dependencies = [ + "profiling-procmacros", +] + +[[package]] +name = "profiling-procmacros" +version = "1.0.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8021cf59c8ec9c432cfc2526ac6b8aa508ecaf29cd415f271b8406c1b851c3fd" +dependencies = [ + "quote", + "syn 2.0.52", +] + +[[package]] +name = "psm" +version = "0.1.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5787f7cda34e3033a72192c018bc5883100330f362ef279a8cbccfce8bb4e874" +dependencies = [ + "cc", +] + +[[package]] +name = "quick-xml" +version = "0.30.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eff6510e86862b57b210fd8cbe8ed3f0d7d600b9c2863cd4549a2e033c66e956" +dependencies = [ + "memchr", + "serde", +] + +[[package]] +name = "quick-xml" +version = "0.31.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1004a344b30a54e2ee58d66a71b32d2db2feb0a31f9a2d302bf0536f15de2a33" +dependencies = [ + "memchr", +] + +[[package]] +name = "quote" +version = "1.0.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "291ec9ab5efd934aaf503a6466c5d5251535d108ee747472c3977cc5acc868ef" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "radix_trie" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c069c179fcdc6a2fe24d8d18305cf085fdbd4f922c041943e203685d6a1c58fd" +dependencies = [ + "endian-type", + "nibble_vec", +] + +[[package]] +name = "rand" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" +dependencies = [ + "libc", + "rand_chacha", + "rand_core", +] + +[[package]] +name = "rand_chacha" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" +dependencies = [ + "ppv-lite86", + "rand_core", +] + +[[package]] +name = "rand_core" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" +dependencies = [ + "getrandom 0.2.12", +] + +[[package]] +name = "rayon" +version = "1.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e4963ed1bc86e4f3ee217022bd855b297cef07fb9eac5dfa1f788b220b49b3bd" +dependencies = [ + "either", + "rayon-core", +] + +[[package]] +name = "rayon-core" +version = "1.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1465873a3dfdaa8ae7cb14b4383657caab0b3e8a0aa9ae8e04b044854c8dfce2" +dependencies = [ + "crossbeam-deque", + "crossbeam-utils", +] + +[[package]] +name = "rbx_binary" +version = "0.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6314dd6bf5c21d0598cdb53cf5d241aa643ba41da8b8abf7402b4a35096f03f6" +dependencies = [ + "log", + "lz4", + "profiling", + "rbx_dom_weak", + "rbx_reflection", + "rbx_reflection_database", + "thiserror", +] + +[[package]] +name = "rbx_cookie" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d8a61b073240f4c13b1e780a8999a113dfa28bc93f2cf9fc41c6f36e7aceb5bf" +dependencies = [ + "byteorder 0.5.3", + "cookie 0.15.2", + "dirs 1.0.5", + "log", + "plist", + "winapi", + "winreg 0.10.1", +] + +[[package]] +name = "rbx_dom_weak" +version = "2.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b67b56bac99849c2e3c57547b036927f71c57cf7f4d900d04e3e4ee774ec316" +dependencies = [ + "rbx_types", + "serde", +] + +[[package]] +name = "rbx_reflection" +version = "4.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0d41509c991b53a7276a746a795eae2b9204f398164920f61976995b47fe1722" +dependencies = [ + "rbx_types", + "serde", + "thiserror", +] + +[[package]] +name = "rbx_reflection_database" +version = "0.2.10+roblox-607" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "12e20c06fa41f7aadc79005c8354f592b2c2f4d0c61e1080ed5718dafc30aea0" +dependencies = [ + "lazy_static", + "rbx_reflection", + "rmp-serde", + "serde", +] + +[[package]] +name = "rbx_types" +version = "1.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7ca23bfd469d067d81ef14f65fe09aeddc25abcf576a889d1a7664fe021cf18c" +dependencies = [ + "base64 0.13.1", + "bitflags 1.3.2", + "blake3", + "lazy_static", + "rand", + "serde", + "thiserror", +] + +[[package]] +name = "rbx_xml" +version = "0.13.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8c03f95500961c32340791d1fabd4587f6873bdbff077ecca6ae32db7960dea" +dependencies = [ + "base64 0.13.1", + "log", + "rbx_dom_weak", + "rbx_reflection", + "rbx_reflection_database", + "xml-rs", +] + +[[package]] +name = "redox_syscall" +version = "0.1.57" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41cc0f7e4d5d4544e8861606a285bb08d3e70712ccc7d2b84d7c0ccfaf4b05ce" + +[[package]] +name = "redox_syscall" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4722d768eff46b75989dd134e5c353f0d6296e5aaa3132e776cbdb56be7731aa" +dependencies = [ + "bitflags 1.3.2", +] + +[[package]] +name = "redox_users" +version = "0.3.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "de0737333e7a9502c789a36d7c7fa6092a49895d4faa31ca5df163857ded2e9d" +dependencies = [ + "getrandom 0.1.16", + "redox_syscall 0.1.57", + "rust-argon2", +] + +[[package]] +name = "redox_users" +version = "0.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a18479200779601e498ada4e8c1e1f50e3ee19deb0259c25825a98b5603b2cb4" +dependencies = [ + "getrandom 0.2.12", + "libredox", + "thiserror", +] + +[[package]] +name = "regex" +version = "1.10.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b62dbe01f0b06f9d8dc7d49e05a0785f153b00b2c227856282f671e0318c9b15" +dependencies = [ + "aho-corasick", + "memchr", + "regex-automata 0.4.5", + "regex-syntax 0.8.2", +] + +[[package]] +name = "regex-automata" +version = "0.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c230d73fb8d8c1b9c0b3135c5142a8acee3a0558fb8db5cf1cb65f8d7862132" +dependencies = [ + "regex-syntax 0.6.29", +] + +[[package]] +name = "regex-automata" +version = "0.4.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5bb987efffd3c6d0d8f5f89510bb458559eab11e4f869acb20bf845e016259cd" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax 0.8.2", +] + +[[package]] +name = "regex-syntax" +version = "0.6.29" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f162c6dd7b008981e4d40210aca20b4bd0f9b60ca9271061b07f78537722f2e1" + +[[package]] +name = "regex-syntax" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c08c74e62047bb2de4ff487b251e4a92e24f48745648451635cec7d591162d9f" + +[[package]] +name = "relative-path" +version = "1.9.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e898588f33fdd5b9420719948f9f2a32c922a246964576f71ba7f24f80610fbc" +dependencies = [ + "serde", +] + +[[package]] +name = "reqwest" +version = "0.11.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c6920094eb85afde5e4a138be3f2de8bbdf28000f0029e72c45025a56b042251" +dependencies = [ + "base64 0.21.7", + "bytes", + "encoding_rs", + "futures-core", + "futures-util", + "h2", + "http", + "http-body", + "hyper", + "hyper-rustls", + "hyper-tls", + "ipnet", + "js-sys", + "log", + "mime", + "mime_guess", + "native-tls", + "once_cell", + "percent-encoding", + "pin-project-lite", + "rustls", + "rustls-pemfile", + "serde", + "serde_json", + "serde_urlencoded", + "sync_wrapper", + "system-configuration", + "tokio", + "tokio-native-tls", + "tokio-rustls", + "tower-service", + "url", + "wasm-bindgen", + "wasm-bindgen-futures", + "web-sys", + "webpki-roots", + "winreg 0.50.0", +] + +[[package]] +name = "ring" +version = "0.17.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c17fa4cb658e3583423e915b9f3acc01cceaee1860e33d59ebae66adc3a2dc0d" +dependencies = [ + "cc", + "cfg-if", + "getrandom 0.2.12", + "libc", + "spin", + "untrusted", + "windows-sys 0.52.0", +] + +[[package]] +name = "rmp" +version = "0.8.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f9860a6cc38ed1da53456442089b4dfa35e7cedaa326df63017af88385e6b20" +dependencies = [ + "byteorder 1.5.0", + "num-traits", + "paste", +] + +[[package]] +name = "rmp-serde" +version = "1.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bffea85eea980d8a74453e5d02a8d93028f3c34725de143085a844ebe953258a" +dependencies = [ + "byteorder 1.5.0", + "rmp", + "serde", +] + +[[package]] +name = "rust-argon2" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4b18820d944b33caa75a71378964ac46f58517c92b6ae5f762636247c09e78fb" +dependencies = [ + "base64 0.13.1", + "blake2b_simd", + "constant_time_eq 0.1.5", + "crossbeam-utils", +] + +[[package]] +name = "rust-stemmers" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e46a2036019fdb888131db7a4c847a1063a7493f971ed94ea82c67eada63ca54" +dependencies = [ + "serde", + "serde_derive", +] + +[[package]] +name = "rustc-demangle" +version = "0.1.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76" + +[[package]] +name = "rustc-hash" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" + +[[package]] +name = "rustc_version" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a" +dependencies = [ + "semver 0.9.0", +] + +[[package]] +name = "rustc_version" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bfa0f585226d2e68097d4f95d113b15b83a82e819ab25717ec0590d9584ef366" +dependencies = [ + "semver 1.0.22", +] + +[[package]] +name = "rustix" +version = "0.37.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fea8ca367a3a01fe35e6943c400addf443c0f57670e6ec51196f71a4b8762dd2" +dependencies = [ + "bitflags 1.3.2", + "errno", + "io-lifetimes", + "libc", + "linux-raw-sys 0.3.8", + "windows-sys 0.48.0", +] + +[[package]] +name = "rustix" +version = "0.38.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ea3e1a662af26cd7a3ba09c0297a31af215563ecf42817c98df621387f4e949" +dependencies = [ + "bitflags 2.4.2", + "errno", + "libc", + "linux-raw-sys 0.4.13", + "windows-sys 0.52.0", +] + +[[package]] +name = "rustls" +version = "0.21.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f9d5a6813c0759e4609cd494e8e725babae6a2ca7b62a5536a13daaec6fcb7ba" +dependencies = [ + "log", + "ring", + "rustls-webpki", + "sct", +] + +[[package]] +name = "rustls-pemfile" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1c74cae0a4cf6ccbbf5f359f08efdf8ee7e1dc532573bf0db71968cb56b1448c" +dependencies = [ + "base64 0.21.7", +] + +[[package]] +name = "rustls-webpki" +version = "0.101.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b6275d1ee7a1cd780b64aca7726599a1dbc893b1e64144529e55c3c2f745765" +dependencies = [ + "ring", + "untrusted", +] + +[[package]] +name = "rustversion" +version = "1.0.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7ffc183a10b4478d04cbbbfc96d0873219d962dd5accaff2ffbd4ceb7df837f4" + +[[package]] +name = "rusty-s3" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "31aa883f1b986a5249641e574ca0e11ac4fb9970b009c6fbb96fedaf4fa78db8" +dependencies = [ + "base64 0.21.7", + "hmac", + "md-5", + "percent-encoding", + "quick-xml 0.30.0", + "serde", + "serde_json", + "sha2", + "time 0.3.34", + "url", + "zeroize", +] + +[[package]] +name = "rustyline" +version = "13.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "02a2d683a4ac90aeef5b1013933f6d977bd37d51ff3f4dad829d4931a7e6be86" +dependencies = [ + "bitflags 2.4.2", + "cfg-if", + "clipboard-win", + "fd-lock", + "home", + "libc", + "log", + "memchr", + "nix 0.27.1", + "radix_trie", + "unicode-segmentation", + "unicode-width", + "utf8parse", + "winapi", +] + +[[package]] +name = "ryu" +version = "1.0.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e86697c916019a8588c99b5fac3cead74ec0b4b819707a682fd4d23fa0ce1ba1" + +[[package]] +name = "safemem" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ef703b7cb59335eae2eb93ceb664c0eb7ea6bf567079d843e09420219668e072" + +[[package]] +name = "same-file" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502" +dependencies = [ + "winapi-util", +] + +[[package]] +name = "schannel" +version = "0.1.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fbc91545643bcf3a0bbb6569265615222618bdf33ce4ffbbd13c4bbd4c093534" +dependencies = [ + "windows-sys 0.52.0", +] + +[[package]] +name = "scoped-tls" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e1cf6437eb19a8f4a6cc0f7dca544973b0b78843adbfeb3683d1a94a0024a294" + +[[package]] +name = "scopeguard" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" + +[[package]] +name = "sct" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da046153aa2352493d6cb7da4b6e5c0c057d8a1d0a9aa8560baffdd945acd414" +dependencies = [ + "ring", + "untrusted", +] + +[[package]] +name = "secret-service" +version = "3.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5da1a5ad4d28c03536f82f77d9f36603f5e37d8869ac98f0a750d5b5686d8d95" +dependencies = [ + "aes", + "block-modes", + "futures-util", + "generic-array", + "hkdf", + "num", + "once_cell", + "rand", + "serde", + "sha2", + "zbus", +] + +[[package]] +name = "security-framework" +version = "2.9.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05b64fb303737d99b81884b2c63433e9ae28abebe5eb5045dcdd175dc2ecf4de" +dependencies = [ + "bitflags 1.3.2", + "core-foundation", + "core-foundation-sys", + "libc", + "security-framework-sys", +] + +[[package]] +name = "security-framework-sys" +version = "2.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e932934257d3b408ed8f30db49d85ea163bfe74961f017f405b025af298f0c7a" +dependencies = [ + "core-foundation-sys", + "libc", +] + +[[package]] +name = "semver" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403" +dependencies = [ + "semver-parser", +] + +[[package]] +name = "semver" +version = "1.0.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "92d43fe69e652f3df9bdc2b85b2854a0825b86e4fb76bc44d945137d053639ca" +dependencies = [ + "serde", +] + +[[package]] +name = "semver-parser" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" + +[[package]] +name = "sentry" +version = "0.32.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "766448f12e44d68e675d5789a261515c46ac6ccd240abdd451a9c46c84a49523" +dependencies = [ + "httpdate", + "native-tls", + "reqwest", + "sentry-backtrace", + "sentry-contexts", + "sentry-core", + "sentry-debug-images", + "sentry-panic", + "sentry-tracing", + "tokio", + "ureq", +] + +[[package]] +name = "sentry-actix" +version = "0.32.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "285f2c101ed64f00585ec98f0d81a402c1cf5c2f9b1e1d53a84901812bcd4530" +dependencies = [ + "actix-web", + "futures-util", + "sentry-core", +] + +[[package]] +name = "sentry-backtrace" +version = "0.32.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32701cad8b3c78101e1cd33039303154791b0ff22e7802ed8cc23212ef478b45" +dependencies = [ + "backtrace", + "once_cell", + "regex", + "sentry-core", +] + +[[package]] +name = "sentry-contexts" +version = "0.32.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "17ddd2a91a13805bd8dab4ebf47323426f758c35f7bf24eacc1aded9668f3824" +dependencies = [ + "hostname", + "libc", + "os_info", + "rustc_version 0.4.0", + "sentry-core", + "uname", +] + +[[package]] +name = "sentry-core" +version = "0.32.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1189f68d7e7e102ef7171adf75f83a59607fafd1a5eecc9dc06c026ff3bdec4" +dependencies = [ + "once_cell", + "rand", + "sentry-types", + "serde", + "serde_json", +] + +[[package]] +name = "sentry-debug-images" +version = "0.32.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7b4d0a615e5eeca5699030620c119a094e04c14cf6b486ea1030460a544111a7" +dependencies = [ + "findshlibs", + "once_cell", + "sentry-core", +] + +[[package]] +name = "sentry-log" +version = "0.32.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d2d7cd58e7b31a1a533163abf86c182824ea8f8867853a6b402cde053595a54b" +dependencies = [ + "log", + "sentry-core", +] + +[[package]] +name = "sentry-panic" +version = "0.32.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d1c18d0b5fba195a4950f2f4c31023725c76f00aabb5840b7950479ece21b5ca" +dependencies = [ + "sentry-backtrace", + "sentry-core", +] + +[[package]] +name = "sentry-tracing" +version = "0.32.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3012699a9957d7f97047fd75d116e22d120668327db6e7c59824582e16e791b2" +dependencies = [ + "sentry-backtrace", + "sentry-core", + "tracing-core", + "tracing-subscriber", +] + +[[package]] +name = "sentry-types" +version = "0.32.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c7173fd594569091f68a7c37a886e202f4d0c1db1e1fa1d18a051ba695b2e2ec" +dependencies = [ + "debugid", + "hex", + "rand", + "serde", + "serde_json", + "thiserror", + "time 0.3.34", + "url", + "uuid", +] + +[[package]] +name = "serde" +version = "1.0.197" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3fb1c873e1b9b056a4dc4c0c198b24c3ffa059243875552b2bd0933b1aee4ce2" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde-value" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f3a1a3341211875ef120e117ea7fd5228530ae7e7036a779fdc9117be6b3282c" +dependencies = [ + "ordered-float", + "serde", +] + +[[package]] +name = "serde_derive" +version = "1.0.197" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7eb0b34b42edc17f6b7cac84a52a1c5f0e1bb2227e997ca9011ea3dd34e8610b" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.52", +] + +[[package]] +name = "serde_json" +version = "1.0.114" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c5f09b1bd632ef549eaa9f60a1f8de742bdbc698e6cee2095fc84dde5f549ae0" +dependencies = [ + "indexmap 2.2.5", + "itoa", + "ryu", + "serde", +] + +[[package]] +name = "serde_plain" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ce1fc6db65a611022b23a0dec6975d63fb80a302cb3388835ff02c097258d50" +dependencies = [ + "serde", +] + +[[package]] +name = "serde_repr" +version = "0.1.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b2e6b945e9d3df726b65d6ee24060aff8e3533d431f677a9695db04eff9dfdb" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.52", +] + +[[package]] +name = "serde_spanned" +version = "0.6.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eb3622f419d1296904700073ea6cc23ad690adbd66f13ea683df73298736f0c1" +dependencies = [ + "serde", +] + +[[package]] +name = "serde_urlencoded" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3491c14715ca2294c4d6a88f15e84739788c1d030eed8c110436aafdaa2f3fd" +dependencies = [ + "form_urlencoded", + "itoa", + "ryu", + "serde", +] + +[[package]] +name = "serde_yaml" +version = "0.9.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8fd075d994154d4a774f95b51fb96bdc2832b0ea48425c92546073816cda1f2f" +dependencies = [ + "indexmap 2.2.5", + "itoa", + "ryu", + "serde", + "unsafe-libyaml", +] + +[[package]] +name = "sha1" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c1da05c97445caa12d05e848c4a4fcbbea29e748ac28f7e80e9b010392063770" +dependencies = [ + "sha1_smol", +] + +[[package]] +name = "sha1" +version = "0.10.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3bf829a2d51ab4a5ddf1352d8470c140cadc8301b2ae1789db023f01cedd6ba" +dependencies = [ + "cfg-if", + "cpufeatures", + "digest", +] + +[[package]] +name = "sha1_smol" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae1a47186c03a32177042e55dbc5fd5aee900b8e0069a8d70fba96a9375cd012" + +[[package]] +name = "sha2" +version = "0.10.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "793db75ad2bcafc3ffa7c68b215fee268f537982cd901d132f89c6343f3a3dc8" +dependencies = [ + "cfg-if", + "cpufeatures", + "digest", +] + +[[package]] +name = "sharded-slab" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f40ca3c46823713e0d4209592e8d6e826aa57e928f09752619fc696c499637f6" +dependencies = [ + "lazy_static", +] + +[[package]] +name = "shell-words" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "24188a676b6ae68c3b2cb3a01be17fbf7240ce009799bb56d5b1409051e78fde" + +[[package]] +name = "signal-hook-registry" +version = "1.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d8229b473baa5980ac72ef434c4415e70c4b5e71b423043adb4ba059f89c99a1" +dependencies = [ + "libc", +] + +[[package]] +name = "sketches-ddsketch" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85636c14b73d81f541e525f585c0a2109e6744e1565b5c1668e31c70c10ed65c" +dependencies = [ + "serde", +] + +[[package]] +name = "slab" +version = "0.4.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f92a496fb766b417c996b9c5e57daf2f7ad3b0bebe1ccfca4856390e3d3bb67" +dependencies = [ + "autocfg", +] + +[[package]] +name = "smallvec" +version = "1.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6ecd384b10a64542d77071bd64bd7b231f4ed5940fba55e98c3de13824cf3d7" + +[[package]] +name = "smol_str" +version = "0.1.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fad6c857cbab2627dcf01ec85a623ca4e7dcb5691cbaa3d7fb7653671f0d09c9" +dependencies = [ + "serde", +] + +[[package]] +name = "socket2" +version = "0.4.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9f7916fc008ca5542385b89a3d3ce689953c143e9304a9bf8beec1de48994c0d" +dependencies = [ + "libc", + "winapi", +] + +[[package]] +name = "socket2" +version = "0.5.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05ffd9c0a93b7543e062e759284fcf5f5e3b098501104bfbdde4d404db792871" +dependencies = [ + "libc", + "windows-sys 0.52.0", +] + +[[package]] +name = "spin" +version = "0.9.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67" + +[[package]] +name = "stable_deref_trait" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" + +[[package]] +name = "stacker" +version = "0.1.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c886bd4480155fd3ef527d45e9ac8dd7118a898a46530b7b94c3e21866259fce" +dependencies = [ + "cc", + "cfg-if", + "libc", + "psm", + "winapi", +] + +[[package]] +name = "standback" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e113fb6f3de07a243d434a56ec6f186dfd51cb08448239fe7bcae73f87ff28ff" +dependencies = [ + "version_check", +] + +[[package]] +name = "static_assertions" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" + +[[package]] +name = "stdweb" +version = "0.4.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d022496b16281348b52d0e30ae99e01a73d737b2f45d38fed4edf79f9325a1d5" +dependencies = [ + "discard", + "rustc_version 0.2.3", + "stdweb-derive", + "stdweb-internal-macros", + "stdweb-internal-runtime", + "wasm-bindgen", +] + +[[package]] +name = "stdweb-derive" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c87a60a40fccc84bef0652345bbbbbe20a605bf5d0ce81719fc476f5c03b50ef" +dependencies = [ + "proc-macro2", + "quote", + "serde", + "serde_derive", + "syn 1.0.109", +] + +[[package]] +name = "stdweb-internal-macros" +version = "0.2.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "58fa5ff6ad0d98d1ffa8cb115892b6e69d67799f6763e162a1c9db421dc22e11" +dependencies = [ + "base-x", + "proc-macro2", + "quote", + "serde", + "serde_derive", + "serde_json", + "sha1 0.6.1", + "syn 1.0.109", +] + +[[package]] +name = "stdweb-internal-runtime" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "213701ba3370744dcd1a12960caa4843b3d68b4d1c0a5d575e0d65b2ee9d16c0" + +[[package]] +name = "strsim" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" + +[[package]] +name = "strsim" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5ee073c9e4cd00e28217186dbe12796d692868f432bf2e97ee73bed0c56dfa01" + +[[package]] +name = "subtle" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "81cdd64d312baedb58e21336b31bc043b77e01cc99033ce76ef539f78e965ebc" + +[[package]] +name = "syn" +version = "1.0.109" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "syn" +version = "2.0.52" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b699d15b36d1f02c3e7c69f8ffef53de37aefae075d8488d4ba1a7788d574a07" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "sync_wrapper" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2047c6ded9c721764247e62cd3b03c09ffc529b2ba5b10ec482ae507a4a70160" + +[[package]] +name = "system-configuration" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba3a3adc5c275d719af8cb4272ea1c4a6d668a777f37e115f6d11ddbc1c8e0e7" +dependencies = [ + "bitflags 1.3.2", + "core-foundation", + "system-configuration-sys", +] + +[[package]] +name = "system-configuration-sys" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a75fb188eb626b924683e3b95e3a48e63551fcfb51949de2f06a9d91dbee93c9" +dependencies = [ + "core-foundation-sys", + "libc", +] + +[[package]] +name = "tantivy" +version = "0.21.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d6083cd777fa94271b8ce0fe4533772cb8110c3044bab048d20f70108329a1f2" +dependencies = [ + "aho-corasick", + "arc-swap", + "async-trait", + "base64 0.21.7", + "bitpacking", + "byteorder 1.5.0", + "census", + "crc32fast", + "crossbeam-channel", + "downcast-rs", + "fastdivide", + "fs4", + "htmlescape", + "itertools 0.11.0", + "levenshtein_automata", + "log", + "lru", + "lz4_flex", + "measure_time", + "memmap2", + "murmurhash32", + "num_cpus", + "once_cell", + "oneshot", + "rayon", + "regex", + "rust-stemmers", + "rustc-hash", + "serde", + "serde_json", + "sketches-ddsketch", + "smallvec", + "tantivy-bitpacker", + "tantivy-columnar", + "tantivy-common", + "tantivy-fst", + "tantivy-query-grammar", + "tantivy-stacker", + "tantivy-tokenizer-api", + "tempfile", + "thiserror", + "time 0.3.34", + "uuid", + "winapi", +] + +[[package]] +name = "tantivy-bitpacker" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cecb164321482301f514dd582264fa67f70da2d7eb01872ccd71e35e0d96655a" +dependencies = [ + "bitpacking", +] + +[[package]] +name = "tantivy-columnar" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8d85f8019af9a78b3118c11298b36ffd21c2314bd76bbcd9d12e00124cbb7e70" +dependencies = [ + "fastdivide", + "fnv", + "itertools 0.11.0", + "serde", + "tantivy-bitpacker", + "tantivy-common", + "tantivy-sstable", + "tantivy-stacker", +] + +[[package]] +name = "tantivy-common" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "af4a3a975e604a2aba6b1106a04505e1e7a025e6def477fab6e410b4126471e1" +dependencies = [ + "async-trait", + "byteorder 1.5.0", + "ownedbytes", + "serde", + "time 0.3.34", +] + +[[package]] +name = "tantivy-fst" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc3c506b1a8443a3a65352df6382a1fb6a7afe1a02e871cee0d25e2c3d5f3944" +dependencies = [ + "byteorder 1.5.0", + "regex-syntax 0.6.29", + "utf8-ranges", +] + +[[package]] +name = "tantivy-query-grammar" +version = "0.21.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d39c5a03100ac10c96e0c8b07538e2ab8b17da56434ab348309b31f23fada77" +dependencies = [ + "nom", +] + +[[package]] +name = "tantivy-sstable" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc0c1bb43e5e8b8e05eb8009610344dbf285f06066c844032fbb3e546b3c71df" +dependencies = [ + "tantivy-common", + "tantivy-fst", + "zstd 0.12.4", +] + +[[package]] +name = "tantivy-stacker" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b2c078595413f13f218cf6f97b23dcfd48936838f1d3d13a1016e05acd64ed6c" +dependencies = [ + "murmurhash32", + "tantivy-common", +] + +[[package]] +name = "tantivy-tokenizer-api" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "347b6fb212b26d3505d224f438e3c4b827ab8bd847fe9953ad5ac6b8f9443b66" +dependencies = [ + "serde", +] + +[[package]] +name = "tar" +version = "0.4.40" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b16afcea1f22891c49a00c751c7b63b2233284064f11a200fc624137c51e2ddb" +dependencies = [ + "filetime", + "libc", + "xattr", +] + +[[package]] +name = "tempfile" +version = "3.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85b77fafb263dd9d05cbeac119526425676db3784113aa9295c88498cbf8bff1" +dependencies = [ + "cfg-if", + "fastrand 2.0.1", + "rustix 0.38.31", + "windows-sys 0.52.0", +] + +[[package]] +name = "termcolor" +version = "1.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "06794f8f6c5c898b3275aebefa6b8a1cb24cd2c6c79397ab15774837a0bc5755" +dependencies = [ + "winapi-util", +] + +[[package]] +name = "terminal-prompt" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "572818b3472910acbd5dff46a3413715c18e934b071ab2ba464a7b2c2af16376" +dependencies = [ + "libc", + "winapi", +] + +[[package]] +name = "thiserror" +version = "1.0.57" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e45bcbe8ed29775f228095caf2cd67af7a4ccf756ebff23a306bf3e8b47b24b" +dependencies = [ + "thiserror-impl", +] + +[[package]] +name = "thiserror-impl" +version = "1.0.57" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a953cb265bef375dae3de6663da4d3804eee9682ea80d8e2542529b73c531c81" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.52", +] + +[[package]] +name = "thread_local" +version = "1.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b9ef9bad013ada3808854ceac7b46812a6465ba368859a37e2100283d2d719c" +dependencies = [ + "cfg-if", + "once_cell", +] + +[[package]] +name = "threadpool" +version = "1.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d050e60b33d41c19108b32cea32164033a9013fe3b46cbd4457559bfbf77afaa" +dependencies = [ + "num_cpus", +] + +[[package]] +name = "time" +version = "0.2.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4752a97f8eebd6854ff91f1c1824cd6160626ac4bd44287f7f4ea2035a02a242" +dependencies = [ + "const_fn", + "libc", + "standback", + "stdweb", + "time-macros 0.1.1", + "version_check", + "winapi", +] + +[[package]] +name = "time" +version = "0.3.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c8248b6521bb14bc45b4067159b9b6ad792e2d6d754d6c41fb50e29fefe38749" +dependencies = [ + "deranged", + "itoa", + "num-conv", + "powerfmt", + "serde", + "time-core", + "time-macros 0.2.17", +] + +[[package]] +name = "time-core" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ef927ca75afb808a4d64dd374f00a2adf8d0fcff8e7b184af886c3c87ec4a3f3" + +[[package]] +name = "time-macros" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "957e9c6e26f12cb6d0dd7fc776bb67a706312e7299aed74c8dd5b17ebb27e2f1" +dependencies = [ + "proc-macro-hack", + "time-macros-impl", +] + +[[package]] +name = "time-macros" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7ba3a3ef41e6672a2f0f001392bb5dcd3ff0a9992d618ca761a11c3121547774" +dependencies = [ + "num-conv", + "time-core", +] + +[[package]] +name = "time-macros-impl" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fd3c141a1b43194f3f56a1411225df8646c55781d5f26db825b3d98507eb482f" +dependencies = [ + "proc-macro-hack", + "proc-macro2", + "quote", + "standback", + "syn 1.0.109", +] + +[[package]] +name = "tinyvec" +version = "1.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87cc5ceb3875bb20c2890005a4e226a4651264a5c75edb2421b52861a0a0cb50" +dependencies = [ + "tinyvec_macros", +] + +[[package]] +name = "tinyvec_macros" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" + +[[package]] +name = "tokio" +version = "1.36.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "61285f6515fa018fb2d1e46eb21223fff441ee8db5d0f1435e8ab4f5cdb80931" +dependencies = [ + "backtrace", + "bytes", + "libc", + "mio", + "num_cpus", + "parking_lot", + "pin-project-lite", + "signal-hook-registry", + "socket2 0.5.6", + "tokio-macros", + "tracing", + "windows-sys 0.48.0", +] + +[[package]] +name = "tokio-macros" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b8a1e28f2deaa14e508979454cb3a223b10b938b45af148bc0986de36f1923b" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.52", +] + +[[package]] +name = "tokio-native-tls" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbae76ab933c85776efabc971569dd6119c580d8f5d448769dec1764bf796ef2" +dependencies = [ + "native-tls", + "tokio", +] + +[[package]] +name = "tokio-rustls" +version = "0.24.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c28327cf380ac148141087fbfb9de9d7bd4e84ab5d2c28fbc911d753de8a7081" +dependencies = [ + "rustls", + "tokio", +] + +[[package]] +name = "tokio-tungstenite" +version = "0.20.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "212d5dcb2a1ce06d81107c3d0ffa3121fe974b73f068c8282cb1c32328113b6c" +dependencies = [ + "futures-util", + "log", + "rustls", + "tokio", + "tokio-rustls", + "tungstenite", + "webpki-roots", +] + +[[package]] +name = "tokio-util" +version = "0.7.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5419f34732d9eb6ee4c3578b7989078579b7f039cbbb9ca2c4da015749371e15" +dependencies = [ + "bytes", + "futures-core", + "futures-sink", + "pin-project-lite", + "tokio", + "tracing", +] + +[[package]] +name = "toml" +version = "0.8.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a9aad4a3066010876e8dcf5a8a06e70a558751117a145c6ce2b82c2e2054290" +dependencies = [ + "indexmap 2.2.5", + "serde", + "serde_spanned", + "toml_datetime", + "toml_edit 0.22.6", +] + +[[package]] +name = "toml_datetime" +version = "0.6.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3550f4e9685620ac18a50ed434eb3aec30db8ba93b0287467bca5826ea25baf1" +dependencies = [ + "serde", +] + +[[package]] +name = "toml_edit" +version = "0.19.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b5bb770da30e5cbfde35a2d7b9b8a2c4b8ef89548a7a6aeab5c9a576e3e7421" +dependencies = [ + "indexmap 2.2.5", + "toml_datetime", + "winnow 0.5.40", +] + +[[package]] +name = "toml_edit" +version = "0.22.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2c1b5fd4128cc8d3e0cb74d4ed9a9cc7c7284becd4df68f5f940e1ad123606f6" +dependencies = [ + "indexmap 2.2.5", + "serde", + "serde_spanned", + "toml_datetime", + "winnow 0.6.5", +] + +[[package]] +name = "tower-service" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6bc1c9ce2b5135ac7f93c72918fc37feb872bdc6a5533a8b85eb4b86bfdae52" + +[[package]] +name = "tracing" +version = "0.1.40" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3523ab5a71916ccf420eebdf5521fcef02141234bbc0b8a49f2fdc4544364ef" +dependencies = [ + "log", + "pin-project-lite", + "tracing-attributes", + "tracing-core", +] + +[[package]] +name = "tracing-attributes" +version = "0.1.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.52", +] + +[[package]] +name = "tracing-core" +version = "0.1.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c06d3da6113f116aaee68e4d601191614c9053067f9ab7f6edbcb161237daa54" +dependencies = [ + "once_cell", + "valuable", +] + +[[package]] +name = "tracing-log" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee855f1f400bd0e5c02d150ae5de3840039a3f54b025156404e34c23c03f47c3" +dependencies = [ + "log", + "once_cell", + "tracing-core", +] + +[[package]] +name = "tracing-subscriber" +version = "0.3.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ad0f048c97dbd9faa9b7df56362b8ebcaa52adb06b498c050d2f4e32f90a7a8b" +dependencies = [ + "matchers", + "nu-ansi-term", + "once_cell", + "regex", + "sharded-slab", + "smallvec", + "thread_local", + "tracing", + "tracing-core", + "tracing-log", +] + +[[package]] +name = "try-lock" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b" + +[[package]] +name = "tungstenite" +version = "0.20.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9e3dac10fd62eaf6617d3a904ae222845979aec67c615d1c842b4002c7666fb9" +dependencies = [ + "byteorder 1.5.0", + "bytes", + "data-encoding", + "http", + "httparse", + "log", + "rand", + "rustls", + "sha1 0.10.6", + "thiserror", + "url", + "utf-8", +] + +[[package]] +name = "twox-hash" +version = "1.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "97fee6b57c6a41524a810daee9286c02d7752c4253064d0b05472833a438f675" +dependencies = [ + "cfg-if", + "static_assertions", +] + +[[package]] +name = "typenum" +version = "1.17.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825" + +[[package]] +name = "uds_windows" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "89daebc3e6fd160ac4aa9fc8b3bf71e1f74fbf92367ae71fb83a037e8bf164b9" +dependencies = [ + "memoffset 0.9.0", + "tempfile", + "winapi", +] + +[[package]] +name = "uname" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b72f89f0ca32e4db1c04e2a72f5345d59796d4866a1ee0609084569f73683dc8" +dependencies = [ + "libc", +] + +[[package]] +name = "unicase" +version = "2.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f7d2d4dafb69621809a81864c9c1b864479e1235c0dd4e199924b9742439ed89" +dependencies = [ + "version_check", +] + +[[package]] +name = "unicode-bidi" +version = "0.3.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08f95100a766bf4f8f28f90d77e0a5461bbdb219042e7679bebe79004fed8d75" + +[[package]] +name = "unicode-ident" +version = "1.0.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" + +[[package]] +name = "unicode-normalization" +version = "0.1.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a56d1686db2308d901306f92a263857ef59ea39678a5458e7cb17f01415101f5" +dependencies = [ + "tinyvec", +] + +[[package]] +name = "unicode-segmentation" +version = "1.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d4c87d22b6e3f4a18d4d40ef354e97c90fcb14dd91d7dc0aa9d8a1172ebf7202" + +[[package]] +name = "unicode-width" +version = "0.1.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e51733f11c9c4f72aa0c160008246859e340b00807569a0da0e7a1079b27ba85" + +[[package]] +name = "unsafe-libyaml" +version = "0.2.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ab4c90930b95a82d00dc9e9ac071b4991924390d46cbd0dfe566148667605e4b" + +[[package]] +name = "untrusted" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" + +[[package]] +name = "ureq" +version = "2.9.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "11f214ce18d8b2cbe84ed3aa6486ed3f5b285cf8d8fbdbce9f3f767a724adc35" +dependencies = [ + "base64 0.21.7", + "log", + "native-tls", + "once_cell", + "url", +] + +[[package]] +name = "url" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "31e6302e3bb753d46e83516cae55ae196fc0c309407cf11ab35cc51a4c2a4633" +dependencies = [ + "form_urlencoded", + "idna", + "percent-encoding", + "serde", +] + +[[package]] +name = "urlencoding" +version = "2.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "daf8dba3b7eb870caf1ddeed7bc9d2a049f3cfdfae7cb521b087cc33ae4c49da" + +[[package]] +name = "utf-8" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09cc8ee72d2a9becf2f2febe0205bbed8fc6615b7cb429ad062dc7b7ddd036a9" + +[[package]] +name = "utf8-ranges" +version = "1.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7fcfc827f90e53a02eaef5e535ee14266c1d569214c6aa70133a624d8a3164ba" + +[[package]] +name = "utf8parse" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a" + +[[package]] +name = "uuid" +version = "1.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f00cc9702ca12d3c81455259621e676d0f7251cec66a21e98fe2e9a37db93b2a" +dependencies = [ + "getrandom 0.2.12", + "serde", +] + +[[package]] +name = "valuable" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "830b7e5d4d90034032940e4ace0d9a9a057e7a45cd94e6c007832e39edb82f6d" + +[[package]] +name = "vcpkg" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" + +[[package]] +name = "version_check" +version = "0.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" + +[[package]] +name = "waker-fn" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f3c4517f54858c779bbcbf228f4fca63d121bf85fbecb2dc578cdf4a39395690" + +[[package]] +name = "walkdir" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "29790946404f91d9c5d06f9874efddea1dc06c5efe94541a7d6863108e3a5e4b" +dependencies = [ + "same-file", + "winapi-util", +] + +[[package]] +name = "want" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bfa7760aed19e106de2c7c0b581b509f2f25d3dacaf737cb82ac61bc6d760b0e" +dependencies = [ + "try-lock", +] + +[[package]] +name = "wasi" +version = "0.9.0+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cccddf32554fecc6acb585f82a32a72e28b48f8c4c1883ddfeeeaa96f7d8e519" + +[[package]] +name = "wasi" +version = "0.11.0+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" + +[[package]] +name = "wasm-bindgen" +version = "0.2.91" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c1e124130aee3fb58c5bdd6b639a0509486b0338acaaae0c84a5124b0f588b7f" +dependencies = [ + "cfg-if", + "wasm-bindgen-macro", +] + +[[package]] +name = "wasm-bindgen-backend" +version = "0.2.91" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c9e7e1900c352b609c8488ad12639a311045f40a35491fb69ba8c12f758af70b" +dependencies = [ + "bumpalo", + "log", + "once_cell", + "proc-macro2", + "quote", + "syn 2.0.52", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-futures" +version = "0.4.41" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "877b9c3f61ceea0e56331985743b13f3d25c406a7098d45180fb5f09bc19ed97" +dependencies = [ + "cfg-if", + "js-sys", + "wasm-bindgen", + "web-sys", +] + +[[package]] +name = "wasm-bindgen-macro" +version = "0.2.91" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b30af9e2d358182b5c7449424f017eba305ed32a7010509ede96cdc4696c46ed" +dependencies = [ + "quote", + "wasm-bindgen-macro-support", +] + +[[package]] +name = "wasm-bindgen-macro-support" +version = "0.2.91" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "642f325be6301eb8107a83d12a8ac6c1e1c54345a7ef1a9261962dfefda09e66" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.52", + "wasm-bindgen-backend", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-shared" +version = "0.2.91" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4f186bd2dcf04330886ce82d6f33dd75a7bfcf69ecf5763b89fcde53b6ac9838" + +[[package]] +name = "web-sys" +version = "0.3.68" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "96565907687f7aceb35bc5fc03770a8a0471d82e479f25832f54a0e3f4b28446" +dependencies = [ + "js-sys", + "wasm-bindgen", +] + +[[package]] +name = "webpki-roots" +version = "0.25.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5f20c57d8d7db6d3b86154206ae5d8fba62dd39573114de97c2cb0578251f8e1" + +[[package]] +name = "winapi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" +dependencies = [ + "winapi-i686-pc-windows-gnu", + "winapi-x86_64-pc-windows-gnu", +] + +[[package]] +name = "winapi-i686-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" + +[[package]] +name = "winapi-util" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f29e6f9198ba0d26b4c9f07dbe6f9ed633e1f3d5b8b414090084349e46a52596" +dependencies = [ + "winapi", +] + +[[package]] +name = "winapi-x86_64-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" + +[[package]] +name = "windows" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "efc5cf48f83140dcaab716eeaea345f9e93d0018fb81162753a3f76c3397b538" +dependencies = [ + "windows-core 0.53.0", + "windows-targets 0.52.4", +] + +[[package]] +name = "windows-core" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9" +dependencies = [ + "windows-targets 0.52.4", +] + +[[package]] +name = "windows-core" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9dcc5b895a6377f1ab9fa55acedab1fd5ac0db66ad1e6c7f47e28a22e446a5dd" +dependencies = [ + "windows-result", + "windows-targets 0.52.4", +] + +[[package]] +name = "windows-result" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cd19df78e5168dfb0aedc343d1d1b8d422ab2db6756d2dc3fef75035402a3f64" +dependencies = [ + "windows-targets 0.52.4", +] + +[[package]] +name = "windows-sys" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" +dependencies = [ + "windows-targets 0.48.5", +] + +[[package]] +name = "windows-sys" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" +dependencies = [ + "windows-targets 0.52.4", +] + +[[package]] +name = "windows-targets" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c" +dependencies = [ + "windows_aarch64_gnullvm 0.48.5", + "windows_aarch64_msvc 0.48.5", + "windows_i686_gnu 0.48.5", + "windows_i686_msvc 0.48.5", + "windows_x86_64_gnu 0.48.5", + "windows_x86_64_gnullvm 0.48.5", + "windows_x86_64_msvc 0.48.5", +] + +[[package]] +name = "windows-targets" +version = "0.52.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7dd37b7e5ab9018759f893a1952c9420d060016fc19a472b4bb20d1bdd694d1b" +dependencies = [ + "windows_aarch64_gnullvm 0.52.4", + "windows_aarch64_msvc 0.52.4", + "windows_i686_gnu 0.52.4", + "windows_i686_msvc 0.52.4", + "windows_x86_64_gnu 0.52.4", + "windows_x86_64_gnullvm 0.52.4", + "windows_x86_64_msvc 0.52.4", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.52.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bcf46cf4c365c6f2d1cc93ce535f2c8b244591df96ceee75d8e83deb70a9cac9" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.52.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da9f259dd3bcf6990b55bffd094c4f7235817ba4ceebde8e6d11cd0c5633b675" + +[[package]] +name = "windows_i686_gnu" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" + +[[package]] +name = "windows_i686_gnu" +version = "0.52.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b474d8268f99e0995f25b9f095bc7434632601028cf86590aea5c8a5cb7801d3" + +[[package]] +name = "windows_i686_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" + +[[package]] +name = "windows_i686_msvc" +version = "0.52.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1515e9a29e5bed743cb4415a9ecf5dfca648ce85ee42e15873c3cd8610ff8e02" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.52.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5eee091590e89cc02ad514ffe3ead9eb6b660aedca2183455434b93546371a03" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.52.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77ca79f2451b49fa9e2af39f0747fe999fcda4f5e241b2898624dca97a1f2177" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.52.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32b752e52a2da0ddfbdbcc6fceadfeede4c939ed16d13e648833a61dfb611ed8" + +[[package]] +name = "winnow" +version = "0.5.40" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f593a95398737aeed53e489c785df13f3618e41dbcd6718c6addbf1395aa6876" +dependencies = [ + "memchr", +] + +[[package]] +name = "winnow" +version = "0.6.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dffa400e67ed5a4dd237983829e66475f0a4a26938c4b04c21baede6262215b8" +dependencies = [ + "memchr", +] + +[[package]] +name = "winreg" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "80d0f4e272c85def139476380b12f9ac60926689dd2e01d4923222f40580869d" +dependencies = [ + "winapi", +] + +[[package]] +name = "winreg" +version = "0.50.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "524e57b2c537c0f9b1e69f1965311ec12182b4122e45035b1508cd24d2adadb1" +dependencies = [ + "cfg-if", + "windows-sys 0.48.0", +] + +[[package]] +name = "xattr" +version = "1.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8da84f1a25939b27f6820d92aed108f83ff920fdf11a7b19366c27c4cda81d4f" +dependencies = [ + "libc", + "linux-raw-sys 0.4.13", + "rustix 0.38.31", +] + +[[package]] +name = "xdg-home" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "21e5a325c3cb8398ad6cf859c1135b25dd29e186679cf2da7581d9679f63b38e" +dependencies = [ + "libc", + "winapi", +] + +[[package]] +name = "xml-rs" +version = "0.8.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fcb9cbac069e033553e8bb871be2fbdffcab578eb25bd0f7c508cedc6dcd75a" + +[[package]] +name = "zbus" +version = "3.15.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "675d170b632a6ad49804c8cf2105d7c31eddd3312555cffd4b740e08e97c25e6" +dependencies = [ + "async-broadcast", + "async-executor", + "async-fs", + "async-io 1.13.0", + "async-lock 2.8.0", + "async-process", + "async-recursion", + "async-task", + "async-trait", + "blocking", + "byteorder 1.5.0", + "derivative", + "enumflags2", + "event-listener 2.5.3", + "futures-core", + "futures-sink", + "futures-util", + "hex", + "nix 0.26.4", + "once_cell", + "ordered-stream", + "rand", + "serde", + "serde_repr", + "sha1 0.10.6", + "static_assertions", + "tracing", + "uds_windows", + "winapi", + "xdg-home", + "zbus_macros", + "zbus_names", + "zvariant", +] + +[[package]] +name = "zbus_macros" +version = "3.15.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7131497b0f887e8061b430c530240063d33bf9455fa34438f388a245da69e0a5" +dependencies = [ + "proc-macro-crate", + "proc-macro2", + "quote", + "regex", + "syn 1.0.109", + "zvariant_utils", +] + +[[package]] +name = "zbus_names" +version = "2.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "437d738d3750bed6ca9b8d423ccc7a8eb284f6b1d6d4e225a0e4e6258d864c8d" +dependencies = [ + "serde", + "static_assertions", + "zvariant", +] + +[[package]] +name = "zerocopy" +version = "0.7.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "74d4d3961e53fa4c9a25a8637fc2bfaf2595b3d3ae34875568a5cf64787716be" +dependencies = [ + "zerocopy-derive", +] + +[[package]] +name = "zerocopy-derive" +version = "0.7.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ce1b18ccd8e73a9321186f97e46f9f04b778851177567b1975109d26a08d2a6" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.52", +] + +[[package]] +name = "zeroize" +version = "1.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "525b4ec142c6b68a2d10f01f7bbf6755599ca3f81ea53b8431b7dd348f5fdb2d" + +[[package]] +name = "zstd" +version = "0.12.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a27595e173641171fc74a1232b7b1c7a7cb6e18222c11e9dfb9888fa424c53c" +dependencies = [ + "zstd-safe 6.0.6", +] + +[[package]] +name = "zstd" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bffb3309596d527cfcba7dfc6ed6052f1d39dfbd7c867aa2e865e4a449c10110" +dependencies = [ + "zstd-safe 7.0.0", +] + +[[package]] +name = "zstd-safe" +version = "6.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee98ffd0b48ee95e6c5168188e44a54550b1564d9d530ee21d5f0eaed1069581" +dependencies = [ + "libc", + "zstd-sys", +] + +[[package]] +name = "zstd-safe" +version = "7.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "43747c7422e2924c11144d5229878b98180ef8b06cca4ab5af37afc8a8d8ea3e" +dependencies = [ + "zstd-sys", +] + +[[package]] +name = "zstd-sys" +version = "2.0.9+zstd.1.5.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9e16efa8a874a0481a574084d34cc26fdb3b99627480f785888deb6386506656" +dependencies = [ + "cc", + "pkg-config", +] + +[[package]] +name = "zvariant" +version = "3.15.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4eef2be88ba09b358d3b58aca6e41cd853631d44787f319a1383ca83424fb2db" +dependencies = [ + "byteorder 1.5.0", + "enumflags2", + "libc", + "serde", + "static_assertions", + "zvariant_derive", +] + +[[package]] +name = "zvariant_derive" +version = "3.15.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "37c24dc0bed72f5f90d1f8bb5b07228cbf63b3c6e9f82d82559d4bae666e7ed9" +dependencies = [ + "proc-macro-crate", + "proc-macro2", + "quote", + "syn 1.0.109", + "zvariant_utils", +] + +[[package]] +name = "zvariant_utils" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7234f0d811589db492d16893e3f21e8e2fd282e6d01b0cddee310322062cc200" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] diff --git a/Cargo.toml b/Cargo.toml new file mode 100644 index 0000000..35755cd --- /dev/null +++ b/Cargo.toml @@ -0,0 +1,56 @@ +[package] +name = "pesde" +version = "0.1.0" +edition = "2021" +license = "MIT" +authors = ["daimond113 "] +description = "A package manager for Roblox" +homepage = "https://pesde.daimond113.com" + +[features] +bin = ["clap", "directories", "keyring", "anyhow", "ignore", "pretty_env_logger", "serde_json", "reqwest/json", "reqwest/multipart", "lune", "futures-executor", "indicatif", "auth-git2", "indicatif-log-bridge"] + +[[bin]] +name = "pesde" +path = "src/main.rs" +required-features = ["bin"] + +[dependencies] +serde = { version = "1.0.197", features = ["derive"] } +serde_yaml = "0.9.32" +git2 = "0.18.2" +semver = { version = "1.0.22", features = ["serde"] } +reqwest = { version = "0.11.24", default-features = false, features = ["rustls-tls", "blocking"] } +tar = "0.4.40" +flate2 = "1.0.28" +pathdiff = "0.2.1" +relative-path = { version = "1.9.2", features = ["serde"] } +log = "0.4.20" +thiserror = "1.0.57" +threadpool = "1.8.1" +full_moon = { version = "0.19.0", features = ["stacker", "roblox"] } + +clap = { version = "4.5.1", features = ["derive"], optional = true } +directories = { version = "5.0.1", optional = true } +keyring = { version = "2.3.2", optional = true } +anyhow = { version = "1.0.80", optional = true } +ignore = { version = "0.4.22", optional = true } +pretty_env_logger = { version = "0.5.0", optional = true } +serde_json = { version = "1.0.114", optional = true } +lune = { version = "0.8.0", optional = true } +futures-executor = { version = "0.3.30", optional = true } +indicatif = { version = "0.17.8", optional = true } +auth-git2 = { version = "0.5.3", optional = true } +indicatif-log-bridge = { version = "0.2.2", optional = true } + +[dev-dependencies] +tempfile = "3.10.1" + +[workspace] +resolver = "2" +members = [ + "registry" +] + +[profile.dev.package.full_moon] +opt-level = 3 \ No newline at end of file diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..d979d09 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,9 @@ +FROM rust:1.76 + +COPY . . + +WORKDIR /registry + +RUN cargo install --path . + +CMD ["pesde-registry"] \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 0000000..455350d --- /dev/null +++ b/README.md @@ -0,0 +1,22 @@ +# pesde + +pesde is a package manager for Roblox that is designed to be feature-rich and easy to use. +Currently, pesde is in a very early stage of development, but already supports the following features: + +- Managing dependencies +- Re-exporting types +- `bin` exports (ran with Lune) +- Patching packages + +## Installation + +pesde can be installed from GitHub Releases. You can find the latest release [here](https://github.com/daimond113/pesde/releases). +It can also be installed by using [Aftman](https://github.com/LPGhatguy/aftman). + +## Hosting + +The pesde registry is hosted on [fly.io](https://fly.io). You can find the registry [here](https://registry.pesde.daimond113.com). + +## Previous art + +pesde is heavily inspired by [npm](https://www.npmjs.com/), [pnpm](https://pnpm.io/), [wally](https://wally.run), and [cargo](https://doc.rust-lang.org/cargo/). It aims to take the best parts of each package manager and combine them into one. diff --git a/cliff.toml b/cliff.toml new file mode 100644 index 0000000..029e7b1 --- /dev/null +++ b/cliff.toml @@ -0,0 +1,86 @@ +[changelog] +header = """ +# Changelog\n +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).\n +""" + +body = """ +{%- macro remote_url() -%} + https://github.com/{{ remote.github.owner }}/{{ remote.github.repo }} +{%- endmacro -%} + +{% if version -%} + ## [{{ version | trim_start_matches(pat="v") }}] - {{ timestamp | date(format="%Y-%m-%d") }} +{% else -%} + ## [Unreleased] +{% endif -%} + +### Details\ + +{% for group, commits in commits | group_by(attribute="group") %} + #### {{ group | upper_first }} + {%- for commit in commits %} + - {{ commit.message | upper_first | trim }}\ + {% if commit.github.username %} by @{{ commit.github.username }}{%- endif -%} + {% if commit.github.pr_number %} in \ + [#{{ commit.github.pr_number }}]({{ self::remote_url() }}/pull/{{ commit.github.pr_number }}) \ + {%- endif -%} + {% endfor %} +{% endfor %} + +{%- if github.contributors | filter(attribute="is_first_time", value=true) | length != 0 %} + ## New Contributors +{%- endif -%} + +{% for contributor in github.contributors | filter(attribute="is_first_time", value=true) %} + * @{{ contributor.username }} made their first contribution + {%- if contributor.pr_number %} in \ + [#{{ contributor.pr_number }}](({{ self::remote_url() }}/pull/{{ contributor.pr_number }}) \ + {%- endif %} +{%- endfor %}\n +""" + +footer = """ +{%- macro remote_url() -%} + https://github.com/{{ remote.github.owner }}/{{ remote.github.repo }} +{%- endmacro -%} + +{% for release in releases -%} + {% if release.version -%} + {% if release.previous.version -%} + [{{ release.version | trim_start_matches(pat="v") }}]: \ + {{ self::remote_url() }}/compare/{{ release.previous.version }}..{{ release.version }} + {% endif -%} + {% else -%} + [unreleased]: {{ self::remote_url() }}/compare/{{ release.previous.version }}..HEAD + {% endif -%} +{% endfor %} + +""" +trim = true + +[git] +conventional_commits = true +filter_unconventional = true +split_commits = false +commit_parsers = [ + { message = "^feat", group = "Features" }, + { message = "^fix", group = "Bug Fixes" }, + { message = "^doc", group = "Documentation", default_scope = "unscoped" }, + { message = "^perf", group = "Performance" }, + { message = "^refactor", group = "Refactor" }, + { message = "^style", group = "Styling" }, + { message = "^test", group = "Testing" }, + { message = "^chore\\(release\\): prepare for", skip = true }, + { message = "^chore", group = "Miscellaneous Tasks" }, + { body = ".*security", group = "Security" }, +] +protect_breaking_commits = true +filter_commits = true +tag_pattern = "v[0-9].*" +ignore_tags = "" +topo_order = true +sort_commits = "newest" \ No newline at end of file diff --git a/fly.toml b/fly.toml new file mode 100644 index 0000000..d4c97ac --- /dev/null +++ b/fly.toml @@ -0,0 +1,31 @@ +# fly.toml app configuration file generated for pesde-registry on 2024-03-04T20:57:13+01:00 +# +# See https://fly.io/docs/reference/configuration/ for information about how to use this file. +# + +app = 'pesde-registry' +primary_region = 'waw' +kill_signal = 'SIGINT' +kill_timeout = '5s' + +[build] + +[env] +ADDRESS = '0.0.0.0' +PORT = '8080' +INDEX_REPO_URL = 'https://github.com/daimond113/pesde-index' +COMITTER_GIT_NAME = 'Pesde Index Updater' +COMITTER_GIT_EMAIL = 'pesde@daimond113.com' + +[http_service] +internal_port = 8080 +force_https = true +auto_stop_machines = true +auto_start_machines = true +min_machines_running = 0 +processes = ['app'] + +[[vm]] +memory = '1gb' +cpu_kind = 'shared' +cpus = 1 diff --git a/registry/.env.example b/registry/.env.example new file mode 100644 index 0000000..778c2a2 --- /dev/null +++ b/registry/.env.example @@ -0,0 +1,11 @@ +INDEX_REPO_URL=# url of the git repository to be used as the package index +S3_ENDPOINT=# endpoint of the s3 bucket +S3_BUCKET_NAME=# name of the s3 bucket +S3_REGION=# region of the s3 bucket +S3_ACCESS_KEY=# access key of the s3 bucket +S3_SECRET_KEY=# secret key of the s3 bucket +COMMITTER_GIT_NAME=# name of the committer used for index updates +COMMITTER_GIT_EMAIL=# email of the committer used for index updates +GITHUB_USERNAME=# username of github account with push access to the index repository +GITHUB_PAT=# personal access token of github account with push access to the index repository +SENTRY_URL=# optional url of sentry error tracking \ No newline at end of file diff --git a/registry/Cargo.lock b/registry/Cargo.lock new file mode 100644 index 0000000..ec1fa89 --- /dev/null +++ b/registry/Cargo.lock @@ -0,0 +1,3201 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "actix-codec" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "617a8268e3537fe1d8c9ead925fca49ef6400927ee7bc26750e90ecee14ce4b8" +dependencies = [ + "bitflags 1.3.2", + "bytes", + "futures-core", + "futures-sink", + "memchr", + "pin-project-lite", + "tokio", + "tokio-util", + "tracing", +] + +[[package]] +name = "actix-cors" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f9e772b3bcafe335042b5db010ab7c09013dad6eac4915c91d8d50902769f331" +dependencies = [ + "actix-utils", + "actix-web", + "derive_more", + "futures-util", + "log", + "once_cell", + "smallvec", +] + +[[package]] +name = "actix-http" +version = "3.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "129d4c88e98860e1758c5de288d1632b07970a16d59bdf7b8d66053d582bb71f" +dependencies = [ + "actix-codec", + "actix-rt", + "actix-service", + "actix-utils", + "ahash", + "base64", + "bitflags 2.4.2", + "brotli", + "bytes", + "bytestring", + "derive_more", + "encoding_rs", + "flate2", + "futures-core", + "h2", + "http", + "httparse", + "httpdate", + "itoa", + "language-tags", + "local-channel", + "mime", + "percent-encoding", + "pin-project-lite", + "rand", + "sha1", + "smallvec", + "tokio", + "tokio-util", + "tracing", + "zstd", +] + +[[package]] +name = "actix-macros" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e01ed3140b2f8d422c68afa1ed2e85d996ea619c988ac834d255db32138655cb" +dependencies = [ + "quote", + "syn 2.0.48", +] + +[[package]] +name = "actix-router" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d22475596539443685426b6bdadb926ad0ecaefdfc5fb05e5e3441f15463c511" +dependencies = [ + "bytestring", + "http", + "regex", + "serde", + "tracing", +] + +[[package]] +name = "actix-rt" +version = "2.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "28f32d40287d3f402ae0028a9d54bef51af15c8769492826a69d28f81893151d" +dependencies = [ + "futures-core", + "tokio", +] + +[[package]] +name = "actix-server" +version = "2.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3eb13e7eef0423ea6eab0e59f6c72e7cb46d33691ad56a726b3cd07ddec2c2d4" +dependencies = [ + "actix-rt", + "actix-service", + "actix-utils", + "futures-core", + "futures-util", + "mio", + "socket2", + "tokio", + "tracing", +] + +[[package]] +name = "actix-service" +version = "2.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3b894941f818cfdc7ccc4b9e60fa7e53b5042a2e8567270f9147d5591893373a" +dependencies = [ + "futures-core", + "paste", + "pin-project-lite", +] + +[[package]] +name = "actix-utils" +version = "3.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "88a1dcdff1466e3c2488e1cb5c36a71822750ad43839937f85d2f4d9f8b705d8" +dependencies = [ + "local-waker", + "pin-project-lite", +] + +[[package]] +name = "actix-web" +version = "4.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e43428f3bf11dee6d166b00ec2df4e3aa8cc1606aaa0b7433c146852e2f4e03b" +dependencies = [ + "actix-codec", + "actix-http", + "actix-macros", + "actix-router", + "actix-rt", + "actix-server", + "actix-service", + "actix-utils", + "actix-web-codegen", + "ahash", + "bytes", + "bytestring", + "cfg-if", + "cookie", + "derive_more", + "encoding_rs", + "futures-core", + "futures-util", + "itoa", + "language-tags", + "log", + "mime", + "once_cell", + "pin-project-lite", + "regex", + "serde", + "serde_json", + "serde_urlencoded", + "smallvec", + "socket2", + "time", + "url", +] + +[[package]] +name = "actix-web-codegen" +version = "4.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eb1f50ebbb30eca122b188319a4398b3f7bb4a8cdf50ecfb73bfc6a3c3ce54f5" +dependencies = [ + "actix-router", + "proc-macro2", + "quote", + "syn 2.0.48", +] + +[[package]] +name = "actix-web-httpauth" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d613edf08a42ccc6864c941d30fe14e1b676a77d16f1dbadc1174d065a0a775" +dependencies = [ + "actix-utils", + "actix-web", + "base64", + "futures-core", + "futures-util", + "log", + "pin-project-lite", +] + +[[package]] +name = "addr2line" +version = "0.21.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a30b2e23b9e17a9f90641c7ab1549cd9b44f296d3ccbf309d2863cfe398a0cb" +dependencies = [ + "gimli", +] + +[[package]] +name = "adler" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" + +[[package]] +name = "ahash" +version = "0.8.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77c3a9648d43b9cd48db467b3f87fdd6e146bcc88ab0180006cef2179fe11d01" +dependencies = [ + "cfg-if", + "getrandom", + "once_cell", + "version_check", + "zerocopy", +] + +[[package]] +name = "aho-corasick" +version = "1.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b2969dcb958b36655471fc61f7e416fa76033bdd4bfed0678d8fee1e2d07a1f0" +dependencies = [ + "memchr", +] + +[[package]] +name = "alloc-no-stdlib" +version = "2.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cc7bb162ec39d46ab1ca8c77bf72e890535becd1751bb45f64c597edb4c8c6b3" + +[[package]] +name = "alloc-stdlib" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94fb8275041c72129eb51b7d0322c29b8387a0386127718b096429201a5d6ece" +dependencies = [ + "alloc-no-stdlib", +] + +[[package]] +name = "allocator-api2" +version = "0.2.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0942ffc6dcaadf03badf6e6a2d0228460359d5e34b57ccdc720b7382dfbd5ec5" + +[[package]] +name = "android-tzdata" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e999941b234f3131b00bc13c22d06e8c5ff726d1b6318ac7eb276997bbb4fef0" + +[[package]] +name = "android_system_properties" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311" +dependencies = [ + "libc", +] + +[[package]] +name = "arc-swap" +version = "1.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bddcadddf5e9015d310179a59bb28c4d4b9920ad0f11e8e14dbadf654890c9a6" + +[[package]] +name = "async-trait" +version = "0.1.77" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c980ee35e870bd1a4d2c8294d4c04d0499e67bca1e4b5cefcc693c2fa00caea9" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.48", +] + +[[package]] +name = "atoi" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f28d99ec8bfea296261ca1af174f24225171fea9664ba9003cbebee704810528" +dependencies = [ + "num-traits", +] + +[[package]] +name = "atomic-write-file" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "edcdbedc2236483ab103a53415653d6b4442ea6141baf1ffa85df29635e88436" +dependencies = [ + "nix", + "rand", +] + +[[package]] +name = "autocfg" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" + +[[package]] +name = "backtrace" +version = "0.3.69" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2089b7e3f35b9dd2d0ed921ead4f6d318c27680d4a5bd167b3ee120edb105837" +dependencies = [ + "addr2line", + "cc", + "cfg-if", + "libc", + "miniz_oxide", + "object", + "rustc-demangle", +] + +[[package]] +name = "base64" +version = "0.21.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d297deb1925b89f2ccc13d7635fa0714f12c87adce1c75356b39ca9b7178567" + +[[package]] +name = "base64ct" +version = "1.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8c3c1a368f70d6cf7302d78f8f7093da241fb8e8807c05cc9e51a125895a6d5b" + +[[package]] +name = "bcrypt" +version = "0.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "28d1c9c15093eb224f0baa400f38fcd713fc1391a6f1c389d886beef146d60a3" +dependencies = [ + "base64", + "blowfish", + "getrandom", + "subtle", + "zeroize", +] + +[[package]] +name = "bitflags" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" + +[[package]] +name = "bitflags" +version = "2.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed570934406eb16438a4e976b1b4500774099c13b8cb96eec99f620f05090ddf" +dependencies = [ + "serde", +] + +[[package]] +name = "block-buffer" +version = "0.10.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71" +dependencies = [ + "generic-array", +] + +[[package]] +name = "blowfish" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e412e2cd0f2b2d93e02543ceae7917b3c70331573df19ee046bcbc35e45e87d7" +dependencies = [ + "byteorder", + "cipher", +] + +[[package]] +name = "brotli" +version = "3.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "516074a47ef4bce09577a3b379392300159ce5b1ba2e501ff1c819950066100f" +dependencies = [ + "alloc-no-stdlib", + "alloc-stdlib", + "brotli-decompressor", +] + +[[package]] +name = "brotli-decompressor" +version = "2.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4e2e4afe60d7dd600fdd3de8d0f08c2b7ec039712e3b6137ff98b7004e82de4f" +dependencies = [ + "alloc-no-stdlib", + "alloc-stdlib", +] + +[[package]] +name = "bumpalo" +version = "3.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f30e7476521f6f8af1a1c4c0b8cc94f0bee37d91763d0ca2665f299b6cd8aec" + +[[package]] +name = "byteorder" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" + +[[package]] +name = "bytes" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a2bd12c1caf447e69cd4528f47f94d203fd2582878ecb9e9465484c4148a8223" + +[[package]] +name = "bytestring" +version = "1.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "74d80203ea6b29df88012294f62733de21cfeab47f17b41af3a38bc30a03ee72" +dependencies = [ + "bytes", +] + +[[package]] +name = "cc" +version = "1.0.83" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1174fb0b6ec23863f8b971027804a42614e347eafb0a95bf0b12cdae21fc4d0" +dependencies = [ + "jobserver", + "libc", +] + +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + +[[package]] +name = "chrono" +version = "0.4.33" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9f13690e35a5e4ace198e7beea2895d29f3a9cc55015fcebe6336bd2010af9eb" +dependencies = [ + "android-tzdata", + "iana-time-zone", + "js-sys", + "num-traits", + "serde", + "wasm-bindgen", + "windows-targets 0.52.0", +] + +[[package]] +name = "cipher" +version = "0.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "773f3b9af64447d2ce9850330c473515014aa235e6a783b02db81ff39e4a3dad" +dependencies = [ + "crypto-common", + "inout", +] + +[[package]] +name = "const-oid" +version = "0.9.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c2459377285ad874054d797f3ccebf984978aa39129f6eafde5cdc8315b612f8" + +[[package]] +name = "convert_case" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6245d59a3e82a7fc217c5828a6692dbc6dfb63a0c8c90495621f7b9d79704a0e" + +[[package]] +name = "cookie" +version = "0.16.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e859cd57d0710d9e06c381b550c06e76992472a8c6d527aecd2fc673dcc231fb" +dependencies = [ + "percent-encoding", + "time", + "version_check", +] + +[[package]] +name = "core-foundation" +version = "0.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "91e195e091a93c46f7102ec7818a2aa394e1e1771c3ab4825963fa03e45afb8f" +dependencies = [ + "core-foundation-sys", + "libc", +] + +[[package]] +name = "core-foundation-sys" +version = "0.8.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "06ea2b9bc92be3c2baa9334a323ebca2d6f074ff852cd1d7b11064035cd3868f" + +[[package]] +name = "cpufeatures" +version = "0.2.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "53fe5e26ff1b7aef8bca9c6080520cfb8d9333c7568e1829cef191a9723e5504" +dependencies = [ + "libc", +] + +[[package]] +name = "crc" +version = "3.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "86ec7a15cbe22e59248fc7eadb1907dab5ba09372595da4d73dd805ed4417dfe" +dependencies = [ + "crc-catalog", +] + +[[package]] +name = "crc-catalog" +version = "2.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "19d374276b40fb8bbdee95aef7c7fa6b5316ec764510eb64b8dd0e2ed0d7e7f5" + +[[package]] +name = "crc32fast" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b540bd8bc810d3885c6ea91e2018302f68baba2129ab3e88f32389ee9370880d" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "crossbeam-queue" +version = "0.3.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df0346b5d5e76ac2fe4e327c5fd1118d6be7c51dfb18f9b7922923f287471e35" +dependencies = [ + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-utils" +version = "0.8.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "248e3bacc7dc6baa3b21e405ee045c3047101a49145e7e9eca583ab4c2ca5345" + +[[package]] +name = "crypto-common" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" +dependencies = [ + "generic-array", + "typenum", +] + +[[package]] +name = "cuid-util" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5ea2bfe0336ff1b7ca74819b2df8dfae9afea358aff6b1688baa5c181d8c3713" + +[[package]] +name = "cuid2" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "47d99cacd52fd67db7490ad051c8c1973fb75520174d69aabbae08c534c9d0e8" +dependencies = [ + "cuid-util", + "num", + "rand", + "sha3", +] + +[[package]] +name = "der" +version = "0.7.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fffa369a668c8af7dbf8b5e56c9f744fbd399949ed171606040001947de40b1c" +dependencies = [ + "const-oid", + "pem-rfc7468", + "zeroize", +] + +[[package]] +name = "deranged" +version = "0.3.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b42b6fa04a440b495c8b04d0e71b707c585f83cb9cb28cf8cd0d976c315e31b4" +dependencies = [ + "powerfmt", +] + +[[package]] +name = "derive_more" +version = "0.99.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4fb810d30a7c1953f91334de7244731fc3f3c10d7fe163338a35b9f640960321" +dependencies = [ + "convert_case", + "proc-macro2", + "quote", + "rustc_version", + "syn 1.0.109", +] + +[[package]] +name = "digest" +version = "0.10.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" +dependencies = [ + "block-buffer", + "const-oid", + "crypto-common", + "subtle", +] + +[[package]] +name = "doc-comment" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fea41bba32d969b513997752735605054bc0dfa92b4c56bf1189f2e174be7a10" + +[[package]] +name = "dotenvy" +version = "0.15.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1aaf95b3e5c8f23aa320147307562d361db0ae0d51242340f558153b4eb2439b" + +[[package]] +name = "either" +version = "1.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a26ae43d7bcc3b814de94796a5e736d4029efb0ee900c12e2d54c993ad1a1e07" +dependencies = [ + "serde", +] + +[[package]] +name = "encoding_rs" +version = "0.8.33" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7268b386296a025e474d5140678f75d6de9493ae55a5d709eeb9dd08149945e1" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "equivalent" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" + +[[package]] +name = "errno" +version = "0.3.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a258e46cdc063eb8519c00b9fc845fc47bcfca4130e2f08e88665ceda8474245" +dependencies = [ + "libc", + "windows-sys 0.52.0", +] + +[[package]] +name = "etcetera" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "136d1b5283a1ab77bd9257427ffd09d8667ced0570b6f938942bc7568ed5b943" +dependencies = [ + "cfg-if", + "home", + "windows-sys 0.48.0", +] + +[[package]] +name = "event-listener" +version = "2.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0206175f82b8d6bf6652ff7d71a1e27fd2e4efde587fd368662814d6ec1d9ce0" + +[[package]] +name = "fastrand" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "25cbce373ec4653f1a01a31e8a5e5ec0c622dc27ff9c4e6606eefef5cbbed4a5" + +[[package]] +name = "finl_unicode" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8fcfdc7a0362c9f4444381a9e697c79d435fe65b52a37466fc2c1184cee9edc6" + +[[package]] +name = "flate2" +version = "1.0.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "46303f565772937ffe1d394a4fac6f411c6013172fadde9dcdb1e147a086940e" +dependencies = [ + "crc32fast", + "miniz_oxide", +] + +[[package]] +name = "flume" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "55ac459de2512911e4b674ce33cf20befaba382d05b62b008afc1c8b57cbf181" +dependencies = [ + "futures-core", + "futures-sink", + "spin 0.9.8", +] + +[[package]] +name = "fnv" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" + +[[package]] +name = "foreign-types" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1" +dependencies = [ + "foreign-types-shared", +] + +[[package]] +name = "foreign-types-shared" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" + +[[package]] +name = "form_urlencoded" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e13624c2627564efccf4934284bdd98cbaa14e79b0b5a141218e507b3a823456" +dependencies = [ + "percent-encoding", +] + +[[package]] +name = "futures" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "645c6916888f6cb6350d2550b80fb63e734897a8498abe35cfb732b6487804b0" +dependencies = [ + "futures-channel", + "futures-core", + "futures-executor", + "futures-io", + "futures-sink", + "futures-task", + "futures-util", +] + +[[package]] +name = "futures-channel" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eac8f7d7865dcb88bd4373ab671c8cf4508703796caa2b1985a9ca867b3fcb78" +dependencies = [ + "futures-core", + "futures-sink", +] + +[[package]] +name = "futures-core" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dfc6580bb841c5a68e9ef15c77ccc837b40a7504914d52e47b8b0e9bbda25a1d" + +[[package]] +name = "futures-executor" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a576fc72ae164fca6b9db127eaa9a9dda0d61316034f33a0a0d4eda41f02b01d" +dependencies = [ + "futures-core", + "futures-task", + "futures-util", +] + +[[package]] +name = "futures-intrusive" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d930c203dd0b6ff06e0201a4a2fe9149b43c684fd4420555b26d21b1a02956f" +dependencies = [ + "futures-core", + "lock_api", + "parking_lot", +] + +[[package]] +name = "futures-io" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a44623e20b9681a318efdd71c299b6b222ed6f231972bfe2f224ebad6311f0c1" + +[[package]] +name = "futures-macro" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.48", +] + +[[package]] +name = "futures-sink" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9fb8e00e87438d937621c1c6269e53f536c14d3fbd6a042bb24879e57d474fb5" + +[[package]] +name = "futures-task" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38d84fa142264698cdce1a9f9172cf383a0c82de1bddcf3092901442c4097004" + +[[package]] +name = "futures-util" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d6401deb83407ab3da39eba7e33987a73c3df0c82b4bb5813ee871c19c41d48" +dependencies = [ + "futures-channel", + "futures-core", + "futures-io", + "futures-macro", + "futures-sink", + "futures-task", + "memchr", + "pin-project-lite", + "pin-utils", + "slab", +] + +[[package]] +name = "generic-array" +version = "0.14.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" +dependencies = [ + "typenum", + "version_check", +] + +[[package]] +name = "getrandom" +version = "0.2.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "190092ea657667030ac6a35e305e62fc4dd69fd98ac98631e5d3a2b1575a12b5" +dependencies = [ + "cfg-if", + "js-sys", + "libc", + "wasi", + "wasm-bindgen", +] + +[[package]] +name = "gimli" +version = "0.28.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4271d37baee1b8c7e4b708028c57d816cf9d2434acb33a549475f78c181f6253" + +[[package]] +name = "h2" +version = "0.3.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bb2c4422095b67ee78da96fbb51a4cc413b3b25883c7717ff7ca1ab31022c9c9" +dependencies = [ + "bytes", + "fnv", + "futures-core", + "futures-sink", + "futures-util", + "http", + "indexmap", + "slab", + "tokio", + "tokio-util", + "tracing", +] + +[[package]] +name = "hashbrown" +version = "0.14.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "290f1a1d9242c78d09ce40a5e87e7554ee637af1351968159f4952f028f75604" +dependencies = [ + "ahash", + "allocator-api2", +] + +[[package]] +name = "hashlink" +version = "0.8.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e8094feaf31ff591f651a2664fb9cfd92bba7a60ce3197265e9482ebe753c8f7" +dependencies = [ + "hashbrown", +] + +[[package]] +name = "heck" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" +dependencies = [ + "unicode-segmentation", +] + +[[package]] +name = "hex" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" + +[[package]] +name = "hkdf" +version = "0.12.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7b5f8eb2ad728638ea2c7d47a21db23b7b58a72ed6a38256b8a1849f15fbbdf7" +dependencies = [ + "hmac", +] + +[[package]] +name = "hmac" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c49c37c09c17a53d937dfbb742eb3a961d65a994e6bcdcf37e7399d0cc8ab5e" +dependencies = [ + "digest", +] + +[[package]] +name = "home" +version = "0.5.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3d1354bf6b7235cb4a0576c2619fd4ed18183f689b12b006a0ee7329eeff9a5" +dependencies = [ + "windows-sys 0.52.0", +] + +[[package]] +name = "http" +version = "0.2.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8947b1a6fad4393052c7ba1f4cd97bed3e953a95c79c92ad9b051a04611d9fbb" +dependencies = [ + "bytes", + "fnv", + "itoa", +] + +[[package]] +name = "http-body" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7ceab25649e9960c0311ea418d17bee82c0dcec1bd053b5f9a66e265a693bed2" +dependencies = [ + "bytes", + "http", + "pin-project-lite", +] + +[[package]] +name = "http-range-header" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "add0ab9360ddbd88cfeb3bd9574a1d85cfdfa14db10b3e21d3700dbc4328758f" + +[[package]] +name = "httparse" +version = "1.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d897f394bad6a705d5f4104762e116a75639e470d80901eed05a860a95cb1904" + +[[package]] +name = "httpdate" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9" + +[[package]] +name = "hyper" +version = "0.14.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bf96e135eb83a2a8ddf766e426a841d8ddd7449d5f00d34ea02b41d2f19eef80" +dependencies = [ + "bytes", + "futures-channel", + "futures-core", + "futures-util", + "h2", + "http", + "http-body", + "httparse", + "httpdate", + "itoa", + "pin-project-lite", + "socket2", + "tokio", + "tower-service", + "tracing", + "want", +] + +[[package]] +name = "hyper-rustls" +version = "0.24.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec3efd23720e2049821a693cbc7e65ea87c72f1c58ff2f9522ff332b1491e590" +dependencies = [ + "futures-util", + "http", + "hyper", + "log", + "rustls", + "rustls-native-certs", + "tokio", + "tokio-rustls", +] + +[[package]] +name = "hyper-timeout" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbb958482e8c7be4bc3cf272a766a2b0bf1a6755e7a6ae777f017a31d11b13b1" +dependencies = [ + "hyper", + "pin-project-lite", + "tokio", + "tokio-io-timeout", +] + +[[package]] +name = "hyper-tls" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d6183ddfa99b85da61a140bea0efc93fdf56ceaa041b37d553518030827f9905" +dependencies = [ + "bytes", + "hyper", + "native-tls", + "tokio", + "tokio-native-tls", +] + +[[package]] +name = "iana-time-zone" +version = "0.1.59" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6a67363e2aa4443928ce15e57ebae94fd8949958fd1223c4cfc0cd473ad7539" +dependencies = [ + "android_system_properties", + "core-foundation-sys", + "iana-time-zone-haiku", + "js-sys", + "wasm-bindgen", + "windows-core", +] + +[[package]] +name = "iana-time-zone-haiku" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f31827a206f56af32e590ba56d5d2d085f558508192593743f16b2306495269f" +dependencies = [ + "cc", +] + +[[package]] +name = "idna" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7d20d6b07bfbc108882d88ed8e37d39636dcc260e15e30c45e6ba089610b917c" +dependencies = [ + "unicode-bidi", + "unicode-normalization", +] + +[[package]] +name = "idna" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "634d9b1461af396cad843f47fdba5597a4f9e6ddd4bfb6ff5d85028c25cb12f6" +dependencies = [ + "unicode-bidi", + "unicode-normalization", +] + +[[package]] +name = "if_chain" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb56e1aa765b4b4f3aadfab769793b7087bb03a4ea4920644a6d238e2df5b9ed" + +[[package]] +name = "indexmap" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf2a4f498956c7723dc280afc6a37d0dec50b39a29e232c6187ce4503703e8c2" +dependencies = [ + "equivalent", + "hashbrown", +] + +[[package]] +name = "inout" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a0c10553d664a4d0bcff9f4215d0aac67a639cc68ef660840afe309b807bc9f5" +dependencies = [ + "generic-array", +] + +[[package]] +name = "ipnet" +version = "2.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f518f335dce6725a761382244631d86cf0ccb2863413590b31338feb467f9c3" + +[[package]] +name = "iri-string" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "21859b667d66a4c1dacd9df0863b3efb65785474255face87f5bca39dd8407c0" +dependencies = [ + "memchr", + "serde", +] + +[[package]] +name = "itertools" +version = "0.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "25db6b064527c5d482d0423354fcd07a89a2dfe07b67892e62411946db7f07b0" +dependencies = [ + "either", +] + +[[package]] +name = "itoa" +version = "1.0.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1a46d1a171d865aa5f83f92695765caa047a9b4cbae2cbf37dbd613a793fd4c" + +[[package]] +name = "jobserver" +version = "0.1.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8c37f63953c4c63420ed5fd3d6d398c719489b9f872b9fa683262f8edd363c7d" +dependencies = [ + "libc", +] + +[[package]] +name = "js-sys" +version = "0.3.67" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a1d36f1235bc969acba30b7f5990b864423a6068a10f7c90ae8f0112e3a59d1" +dependencies = [ + "wasm-bindgen", +] + +[[package]] +name = "jsonwebtoken" +version = "9.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c7ea04a7c5c055c175f189b6dc6ba036fd62306b58c66c9f6389036c503a3f4" +dependencies = [ + "base64", + "js-sys", + "pem", + "ring", + "serde", + "serde_json", + "simple_asn1", +] + +[[package]] +name = "keccak" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ecc2af9a1119c51f12a14607e783cb977bde58bc069ff0c3da1095e635d70654" +dependencies = [ + "cpufeatures", +] + +[[package]] +name = "language-tags" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d4345964bb142484797b161f473a503a434de77149dd8c7427788c6e13379388" + +[[package]] +name = "lazy_static" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" +dependencies = [ + "spin 0.5.2", +] + +[[package]] +name = "libc" +version = "0.2.152" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13e3bf6590cbc649f4d1a3eefc9d5d6eb746f5200ffb04e5e142700b8faa56e7" + +[[package]] +name = "libm" +version = "0.2.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ec2a862134d2a7d32d7983ddcdd1c4923530833c9f2ea1a44fc5fa473989058" + +[[package]] +name = "libsqlite3-sys" +version = "0.27.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf4e226dcd58b4be396f7bd3c20da8fdee2911400705297ba7d2d7cc2c30f716" +dependencies = [ + "cc", + "pkg-config", + "vcpkg", +] + +[[package]] +name = "linux-raw-sys" +version = "0.4.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "01cda141df6706de531b6c46c3a33ecca755538219bd484262fa09410c13539c" + +[[package]] +name = "local-channel" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6cbc85e69b8df4b8bb8b89ec634e7189099cea8927a276b7384ce5488e53ec8" +dependencies = [ + "futures-core", + "futures-sink", + "local-waker", +] + +[[package]] +name = "local-waker" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4d873d7c67ce09b42110d801813efbc9364414e356be9935700d368351657487" + +[[package]] +name = "lock_api" +version = "0.4.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c168f8615b12bc01f9c17e2eb0cc07dcae1940121185446edc3744920e8ef45" +dependencies = [ + "autocfg", + "scopeguard", +] + +[[package]] +name = "log" +version = "0.4.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f" + +[[package]] +name = "md-5" +version = "0.10.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d89e7ee0cfbedfc4da3340218492196241d89eefb6dab27de5df917a6d2e78cf" +dependencies = [ + "cfg-if", + "digest", +] + +[[package]] +name = "memchr" +version = "2.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "523dc4f511e55ab87b694dc30d0f820d60906ef06413f93d4d7a1385599cc149" + +[[package]] +name = "mime" +version = "0.3.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a" + +[[package]] +name = "minimal-lexical" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" + +[[package]] +name = "miniz_oxide" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e7810e0be55b428ada41041c41f32c9f1a42817901b4ccf45fa3d4b6561e74c7" +dependencies = [ + "adler", +] + +[[package]] +name = "mio" +version = "0.8.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f3d0b296e374a4e6f3c7b0a1f5a51d748a0d34c85e7dc48fc3fa9a87657fe09" +dependencies = [ + "libc", + "log", + "wasi", + "windows-sys 0.48.0", +] + +[[package]] +name = "native-tls" +version = "0.2.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "07226173c32f2926027b63cce4bcd8076c3552846cbe7925f3aaffeac0a3b92e" +dependencies = [ + "lazy_static", + "libc", + "log", + "openssl", + "openssl-probe", + "openssl-sys", + "schannel", + "security-framework", + "security-framework-sys", + "tempfile", +] + +[[package]] +name = "nix" +version = "0.27.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2eb04e9c688eff1c89d72b407f168cf79bb9e867a9d3323ed6c01519eb9cc053" +dependencies = [ + "bitflags 2.4.2", + "cfg-if", + "libc", +] + +[[package]] +name = "nom" +version = "7.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a" +dependencies = [ + "memchr", + "minimal-lexical", +] + +[[package]] +name = "num" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b05180d69e3da0e530ba2a1dae5110317e49e3b7f3d41be227dc5f92e49ee7af" +dependencies = [ + "num-bigint", + "num-complex", + "num-integer", + "num-iter", + "num-rational", + "num-traits", +] + +[[package]] +name = "num-bigint" +version = "0.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "608e7659b5c3d7cba262d894801b9ec9d00de989e8a82bd4bef91d08da45cdc0" +dependencies = [ + "autocfg", + "num-integer", + "num-traits", +] + +[[package]] +name = "num-bigint-dig" +version = "0.8.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc84195820f291c7697304f3cbdadd1cb7199c0efc917ff5eafd71225c136151" +dependencies = [ + "byteorder", + "lazy_static", + "libm", + "num-integer", + "num-iter", + "num-traits", + "rand", + "smallvec", + "zeroize", +] + +[[package]] +name = "num-complex" +version = "0.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ba157ca0885411de85d6ca030ba7e2a83a28636056c7c699b07c8b6f7383214" +dependencies = [ + "num-traits", +] + +[[package]] +name = "num-integer" +version = "0.1.45" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "225d3389fb3509a24c93f5c29eb6bde2586b98d9f016636dff58d7c6f7569cd9" +dependencies = [ + "autocfg", + "num-traits", +] + +[[package]] +name = "num-iter" +version = "0.1.43" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7d03e6c028c5dc5cac6e2dec0efda81fc887605bb3d884578bb6d6bf7514e252" +dependencies = [ + "autocfg", + "num-integer", + "num-traits", +] + +[[package]] +name = "num-rational" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0638a1c9d0a3c0914158145bc76cff373a75a627e6ecbfb71cbe6f453a5a19b0" +dependencies = [ + "autocfg", + "num-bigint", + "num-integer", + "num-traits", +] + +[[package]] +name = "num-traits" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "39e3200413f237f41ab11ad6d161bc7239c84dcb631773ccd7de3dfe4b5c267c" +dependencies = [ + "autocfg", + "libm", +] + +[[package]] +name = "object" +version = "0.32.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a6a622008b6e321afc04970976f62ee297fdbaa6f95318ca343e3eebb9648441" +dependencies = [ + "memchr", +] + +[[package]] +name = "octocrab" +version = "0.33.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "054a8bf47dfa8f89bb0dcf17e485e9f49f2586c05bf0aa67b8ec5a9e7bc8dfd5" +dependencies = [ + "arc-swap", + "async-trait", + "base64", + "bytes", + "cfg-if", + "chrono", + "either", + "futures", + "futures-util", + "http", + "http-body", + "hyper", + "hyper-rustls", + "hyper-timeout", + "jsonwebtoken", + "once_cell", + "percent-encoding", + "pin-project", + "secrecy", + "serde", + "serde_json", + "serde_path_to_error", + "serde_urlencoded", + "snafu", + "tokio", + "tower", + "tower-http", + "tracing", + "url", +] + +[[package]] +name = "once_cell" +version = "1.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" + +[[package]] +name = "openssl" +version = "0.10.63" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "15c9d69dd87a29568d4d017cfe8ec518706046a05184e5aea92d0af890b803c8" +dependencies = [ + "bitflags 2.4.2", + "cfg-if", + "foreign-types", + "libc", + "once_cell", + "openssl-macros", + "openssl-sys", +] + +[[package]] +name = "openssl-macros" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.48", +] + +[[package]] +name = "openssl-probe" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf" + +[[package]] +name = "openssl-sys" +version = "0.9.99" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "22e1bf214306098e4832460f797824c05d25aacdf896f64a985fb0fd992454ae" +dependencies = [ + "cc", + "libc", + "pkg-config", + "vcpkg", +] + +[[package]] +name = "organizations" +version = "0.1.0" + +[[package]] +name = "parking_lot" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3742b2c103b9f06bc9fff0a37ff4912935851bee6d36f3c02bcc755bcfec228f" +dependencies = [ + "lock_api", + "parking_lot_core", +] + +[[package]] +name = "parking_lot_core" +version = "0.9.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c42a9226546d68acdd9c0a280d17ce19bfe27a46bf68784e4066115788d008e" +dependencies = [ + "cfg-if", + "libc", + "redox_syscall", + "smallvec", + "windows-targets 0.48.5", +] + +[[package]] +name = "paste" +version = "1.0.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "de3145af08024dea9fa9914f381a17b8fc6034dfb00f3a84013f7ff43f29ed4c" + +[[package]] +name = "pem" +version = "3.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b8fcc794035347fb64beda2d3b462595dd2753e3f268d89c5aae77e8cf2c310" +dependencies = [ + "base64", + "serde", +] + +[[package]] +name = "pem-rfc7468" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "88b39c9bfcfc231068454382784bb460aae594343fb030d46e9f50a645418412" +dependencies = [ + "base64ct", +] + +[[package]] +name = "percent-encoding" +version = "2.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" + +[[package]] +name = "pin-project" +version = "1.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0302c4a0442c456bd56f841aee5c3bfd17967563f6fadc9ceb9f9c23cf3807e0" +dependencies = [ + "pin-project-internal", +] + +[[package]] +name = "pin-project-internal" +version = "1.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "266c042b60c9c76b8d53061e52b2e0d1116abc57cefc8c5cd671619a56ac3690" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.48", +] + +[[package]] +name = "pin-project-lite" +version = "0.2.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8afb450f006bf6385ca15ef45d71d2288452bc3683ce2e2cacc0d18e4be60b58" + +[[package]] +name = "pin-utils" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" + +[[package]] +name = "pkcs1" +version = "0.7.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c8ffb9f10fa047879315e6625af03c164b16962a5368d724ed16323b68ace47f" +dependencies = [ + "der", + "pkcs8", + "spki", +] + +[[package]] +name = "pkcs8" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f950b2377845cebe5cf8b5165cb3cc1a5e0fa5cfa3e1f7f55707d8fd82e0a7b7" +dependencies = [ + "der", + "spki", +] + +[[package]] +name = "pkg-config" +version = "0.3.29" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2900ede94e305130c13ddd391e0ab7cbaeb783945ae07a279c268cb05109c6cb" + +[[package]] +name = "powerfmt" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391" + +[[package]] +name = "ppv-lite86" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" + +[[package]] +name = "proc-macro-error" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c" +dependencies = [ + "proc-macro-error-attr", + "proc-macro2", + "quote", + "syn 1.0.109", + "version_check", +] + +[[package]] +name = "proc-macro-error-attr" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869" +dependencies = [ + "proc-macro2", + "quote", + "version_check", +] + +[[package]] +name = "proc-macro2" +version = "1.0.78" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2422ad645d89c99f8f3e6b88a9fdeca7fabeac836b1002371c4367c8f984aae" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "quick-xml" +version = "0.30.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eff6510e86862b57b210fd8cbe8ed3f0d7d600b9c2863cd4549a2e033c66e956" +dependencies = [ + "memchr", + "serde", +] + +[[package]] +name = "quote" +version = "1.0.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "291ec9ab5efd934aaf503a6466c5d5251535d108ee747472c3977cc5acc868ef" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "rand" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" +dependencies = [ + "libc", + "rand_chacha", + "rand_core", +] + +[[package]] +name = "rand_chacha" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" +dependencies = [ + "ppv-lite86", + "rand_core", +] + +[[package]] +name = "rand_core" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" +dependencies = [ + "getrandom", +] + +[[package]] +name = "redox_syscall" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4722d768eff46b75989dd134e5c353f0d6296e5aaa3132e776cbdb56be7731aa" +dependencies = [ + "bitflags 1.3.2", +] + +[[package]] +name = "regex" +version = "1.10.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b62dbe01f0b06f9d8dc7d49e05a0785f153b00b2c227856282f671e0318c9b15" +dependencies = [ + "aho-corasick", + "memchr", + "regex-automata", + "regex-syntax", +] + +[[package]] +name = "regex-automata" +version = "0.4.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5bb987efffd3c6d0d8f5f89510bb458559eab11e4f869acb20bf845e016259cd" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax", +] + +[[package]] +name = "regex-syntax" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c08c74e62047bb2de4ff487b251e4a92e24f48745648451635cec7d591162d9f" + +[[package]] +name = "registry" +version = "0.1.0" +dependencies = [ + "actix-cors", + "actix-web", + "actix-web-httpauth", + "bcrypt", + "chrono", + "cuid2", + "derive_more", + "dotenvy", + "log", + "octocrab", + "reqwest", + "rusty-s3", + "serde", + "serde_json", + "sqlx", + "validator", +] + +[[package]] +name = "reqwest" +version = "0.11.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "37b1ae8d9ac08420c66222fb9096fc5de435c3c48542bc5336c51892cffafb41" +dependencies = [ + "base64", + "bytes", + "encoding_rs", + "futures-core", + "futures-util", + "h2", + "http", + "http-body", + "hyper", + "hyper-tls", + "ipnet", + "js-sys", + "log", + "mime", + "native-tls", + "once_cell", + "percent-encoding", + "pin-project-lite", + "serde", + "serde_json", + "serde_urlencoded", + "system-configuration", + "tokio", + "tokio-native-tls", + "tower-service", + "url", + "wasm-bindgen", + "wasm-bindgen-futures", + "web-sys", + "winreg", +] + +[[package]] +name = "ring" +version = "0.17.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "688c63d65483050968b2a8937f7995f443e27041a0f7700aa59b0822aedebb74" +dependencies = [ + "cc", + "getrandom", + "libc", + "spin 0.9.8", + "untrusted", + "windows-sys 0.48.0", +] + +[[package]] +name = "rsa" +version = "0.9.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5d0e5124fcb30e76a7e79bfee683a2746db83784b86289f6251b54b7950a0dfc" +dependencies = [ + "const-oid", + "digest", + "num-bigint-dig", + "num-integer", + "num-traits", + "pkcs1", + "pkcs8", + "rand_core", + "signature", + "spki", + "subtle", + "zeroize", +] + +[[package]] +name = "rustc-demangle" +version = "0.1.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76" + +[[package]] +name = "rustc_version" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bfa0f585226d2e68097d4f95d113b15b83a82e819ab25717ec0590d9584ef366" +dependencies = [ + "semver", +] + +[[package]] +name = "rustix" +version = "0.38.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "322394588aaf33c24007e8bb3238ee3e4c5c09c084ab32bc73890b99ff326bca" +dependencies = [ + "bitflags 2.4.2", + "errno", + "libc", + "linux-raw-sys", + "windows-sys 0.52.0", +] + +[[package]] +name = "rustls" +version = "0.21.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f9d5a6813c0759e4609cd494e8e725babae6a2ca7b62a5536a13daaec6fcb7ba" +dependencies = [ + "log", + "ring", + "rustls-webpki", + "sct", +] + +[[package]] +name = "rustls-native-certs" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a9aace74cb666635c918e9c12bc0d348266037aa8eb599b5cba565709a8dff00" +dependencies = [ + "openssl-probe", + "rustls-pemfile", + "schannel", + "security-framework", +] + +[[package]] +name = "rustls-pemfile" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1c74cae0a4cf6ccbbf5f359f08efdf8ee7e1dc532573bf0db71968cb56b1448c" +dependencies = [ + "base64", +] + +[[package]] +name = "rustls-webpki" +version = "0.101.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b6275d1ee7a1cd780b64aca7726599a1dbc893b1e64144529e55c3c2f745765" +dependencies = [ + "ring", + "untrusted", +] + +[[package]] +name = "rusty-s3" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "31aa883f1b986a5249641e574ca0e11ac4fb9970b009c6fbb96fedaf4fa78db8" +dependencies = [ + "base64", + "hmac", + "md-5", + "percent-encoding", + "quick-xml", + "serde", + "serde_json", + "sha2", + "time", + "url", + "zeroize", +] + +[[package]] +name = "ryu" +version = "1.0.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f98d2aa92eebf49b69786be48e4477826b256916e84a57ff2a4f21923b48eb4c" + +[[package]] +name = "schannel" +version = "0.1.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fbc91545643bcf3a0bbb6569265615222618bdf33ce4ffbbd13c4bbd4c093534" +dependencies = [ + "windows-sys 0.52.0", +] + +[[package]] +name = "scopeguard" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" + +[[package]] +name = "sct" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da046153aa2352493d6cb7da4b6e5c0c057d8a1d0a9aa8560baffdd945acd414" +dependencies = [ + "ring", + "untrusted", +] + +[[package]] +name = "secrecy" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9bd1c54ea06cfd2f6b63219704de0b9b4f72dcc2b8fdef820be6cd799780e91e" +dependencies = [ + "zeroize", +] + +[[package]] +name = "security-framework" +version = "2.9.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05b64fb303737d99b81884b2c63433e9ae28abebe5eb5045dcdd175dc2ecf4de" +dependencies = [ + "bitflags 1.3.2", + "core-foundation", + "core-foundation-sys", + "libc", + "security-framework-sys", +] + +[[package]] +name = "security-framework-sys" +version = "2.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e932934257d3b408ed8f30db49d85ea163bfe74961f017f405b025af298f0c7a" +dependencies = [ + "core-foundation-sys", + "libc", +] + +[[package]] +name = "semver" +version = "1.0.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b97ed7a9823b74f99c7742f5336af7be5ecd3eeafcb1507d1fa93347b1d589b0" + +[[package]] +name = "serde" +version = "1.0.196" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "870026e60fa08c69f064aa766c10f10b1d62db9ccd4d0abb206472bee0ce3b32" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.196" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "33c85360c95e7d137454dc81d9a4ed2b8efd8fbe19cee57357b32b9771fccb67" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.48", +] + +[[package]] +name = "serde_json" +version = "1.0.112" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4d1bd37ce2324cf3bf85e5a25f96eb4baf0d5aa6eba43e7ae8958870c4ec48ed" +dependencies = [ + "itoa", + "ryu", + "serde", +] + +[[package]] +name = "serde_path_to_error" +version = "0.1.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ebd154a240de39fdebcf5775d2675c204d7c13cf39a4c697be6493c8e734337c" +dependencies = [ + "itoa", + "serde", +] + +[[package]] +name = "serde_urlencoded" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3491c14715ca2294c4d6a88f15e84739788c1d030eed8c110436aafdaa2f3fd" +dependencies = [ + "form_urlencoded", + "itoa", + "ryu", + "serde", +] + +[[package]] +name = "sha1" +version = "0.10.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3bf829a2d51ab4a5ddf1352d8470c140cadc8301b2ae1789db023f01cedd6ba" +dependencies = [ + "cfg-if", + "cpufeatures", + "digest", +] + +[[package]] +name = "sha2" +version = "0.10.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "793db75ad2bcafc3ffa7c68b215fee268f537982cd901d132f89c6343f3a3dc8" +dependencies = [ + "cfg-if", + "cpufeatures", + "digest", +] + +[[package]] +name = "sha3" +version = "0.10.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75872d278a8f37ef87fa0ddbda7802605cb18344497949862c0d4dcb291eba60" +dependencies = [ + "digest", + "keccak", +] + +[[package]] +name = "signal-hook-registry" +version = "1.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d8229b473baa5980ac72ef434c4415e70c4b5e71b423043adb4ba059f89c99a1" +dependencies = [ + "libc", +] + +[[package]] +name = "signature" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77549399552de45a898a580c1b41d445bf730df867cc44e6c0233bbc4b8329de" +dependencies = [ + "digest", + "rand_core", +] + +[[package]] +name = "simple_asn1" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "adc4e5204eb1910f40f9cfa375f6f05b68c3abac4b6fd879c8ff5e7ae8a0a085" +dependencies = [ + "num-bigint", + "num-traits", + "thiserror", + "time", +] + +[[package]] +name = "slab" +version = "0.4.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f92a496fb766b417c996b9c5e57daf2f7ad3b0bebe1ccfca4856390e3d3bb67" +dependencies = [ + "autocfg", +] + +[[package]] +name = "smallvec" +version = "1.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6ecd384b10a64542d77071bd64bd7b231f4ed5940fba55e98c3de13824cf3d7" + +[[package]] +name = "snafu" +version = "0.7.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e4de37ad025c587a29e8f3f5605c00f70b98715ef90b9061a815b9e59e9042d6" +dependencies = [ + "backtrace", + "doc-comment", + "snafu-derive", +] + +[[package]] +name = "snafu-derive" +version = "0.7.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "990079665f075b699031e9c08fd3ab99be5029b96f3b78dc0709e8f77e4efebf" +dependencies = [ + "heck", + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "socket2" +version = "0.5.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7b5fac59a5cb5dd637972e5fca70daf0523c9067fcdc4842f053dae04a18f8e9" +dependencies = [ + "libc", + "windows-sys 0.48.0", +] + +[[package]] +name = "spin" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d" + +[[package]] +name = "spin" +version = "0.9.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67" +dependencies = [ + "lock_api", +] + +[[package]] +name = "spki" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d91ed6c858b01f942cd56b37a94b3e0a1798290327d1236e4d9cf4eaca44d29d" +dependencies = [ + "base64ct", + "der", +] + +[[package]] +name = "sqlformat" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ce81b7bd7c4493975347ef60d8c7e8b742d4694f4c49f93e0a12ea263938176c" +dependencies = [ + "itertools", + "nom", + "unicode_categories", +] + +[[package]] +name = "sqlx" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dba03c279da73694ef99763320dea58b51095dfe87d001b1d4b5fe78ba8763cf" +dependencies = [ + "sqlx-core", + "sqlx-macros", + "sqlx-mysql", + "sqlx-postgres", + "sqlx-sqlite", +] + +[[package]] +name = "sqlx-core" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d84b0a3c3739e220d94b3239fd69fb1f74bc36e16643423bd99de3b43c21bfbd" +dependencies = [ + "ahash", + "atoi", + "byteorder", + "bytes", + "crc", + "crossbeam-queue", + "dotenvy", + "either", + "event-listener", + "futures-channel", + "futures-core", + "futures-intrusive", + "futures-io", + "futures-util", + "hashlink", + "hex", + "indexmap", + "log", + "memchr", + "native-tls", + "once_cell", + "paste", + "percent-encoding", + "serde", + "serde_json", + "sha2", + "smallvec", + "sqlformat", + "thiserror", + "tokio", + "tokio-stream", + "tracing", + "url", +] + +[[package]] +name = "sqlx-macros" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "89961c00dc4d7dffb7aee214964b065072bff69e36ddb9e2c107541f75e4f2a5" +dependencies = [ + "proc-macro2", + "quote", + "sqlx-core", + "sqlx-macros-core", + "syn 1.0.109", +] + +[[package]] +name = "sqlx-macros-core" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d0bd4519486723648186a08785143599760f7cc81c52334a55d6a83ea1e20841" +dependencies = [ + "atomic-write-file", + "dotenvy", + "either", + "heck", + "hex", + "once_cell", + "proc-macro2", + "quote", + "serde", + "serde_json", + "sha2", + "sqlx-core", + "sqlx-mysql", + "sqlx-sqlite", + "syn 1.0.109", + "tempfile", + "tokio", + "url", +] + +[[package]] +name = "sqlx-mysql" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e37195395df71fd068f6e2082247891bc11e3289624bbc776a0cdfa1ca7f1ea4" +dependencies = [ + "atoi", + "base64", + "bitflags 2.4.2", + "byteorder", + "bytes", + "crc", + "digest", + "dotenvy", + "either", + "futures-channel", + "futures-core", + "futures-io", + "futures-util", + "generic-array", + "hex", + "hkdf", + "hmac", + "itoa", + "log", + "md-5", + "memchr", + "once_cell", + "percent-encoding", + "rand", + "rsa", + "serde", + "sha1", + "sha2", + "smallvec", + "sqlx-core", + "stringprep", + "thiserror", + "tracing", + "whoami", +] + +[[package]] +name = "sqlx-postgres" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d6ac0ac3b7ccd10cc96c7ab29791a7dd236bd94021f31eec7ba3d46a74aa1c24" +dependencies = [ + "atoi", + "base64", + "bitflags 2.4.2", + "byteorder", + "crc", + "dotenvy", + "etcetera", + "futures-channel", + "futures-core", + "futures-io", + "futures-util", + "hex", + "hkdf", + "hmac", + "home", + "itoa", + "log", + "md-5", + "memchr", + "once_cell", + "rand", + "serde", + "serde_json", + "sha1", + "sha2", + "smallvec", + "sqlx-core", + "stringprep", + "thiserror", + "tracing", + "whoami", +] + +[[package]] +name = "sqlx-sqlite" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "210976b7d948c7ba9fced8ca835b11cbb2d677c59c79de41ac0d397e14547490" +dependencies = [ + "atoi", + "flume", + "futures-channel", + "futures-core", + "futures-executor", + "futures-intrusive", + "futures-util", + "libsqlite3-sys", + "log", + "percent-encoding", + "serde", + "sqlx-core", + "tracing", + "url", + "urlencoding", +] + +[[package]] +name = "stringprep" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bb41d74e231a107a1b4ee36bd1214b11285b77768d2e3824aedafa988fd36ee6" +dependencies = [ + "finl_unicode", + "unicode-bidi", + "unicode-normalization", +] + +[[package]] +name = "subtle" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "81cdd64d312baedb58e21336b31bc043b77e01cc99033ce76ef539f78e965ebc" + +[[package]] +name = "syn" +version = "1.0.109" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "syn" +version = "2.0.48" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0f3531638e407dfc0814761abb7c00a5b54992b849452a0646b7f65c9f770f3f" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "system-configuration" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba3a3adc5c275d719af8cb4272ea1c4a6d668a777f37e115f6d11ddbc1c8e0e7" +dependencies = [ + "bitflags 1.3.2", + "core-foundation", + "system-configuration-sys", +] + +[[package]] +name = "system-configuration-sys" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a75fb188eb626b924683e3b95e3a48e63551fcfb51949de2f06a9d91dbee93c9" +dependencies = [ + "core-foundation-sys", + "libc", +] + +[[package]] +name = "tempfile" +version = "3.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "01ce4141aa927a6d1bd34a041795abd0db1cccba5d5f24b009f694bdf3a1f3fa" +dependencies = [ + "cfg-if", + "fastrand", + "redox_syscall", + "rustix", + "windows-sys 0.52.0", +] + +[[package]] +name = "thiserror" +version = "1.0.56" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d54378c645627613241d077a3a79db965db602882668f9136ac42af9ecb730ad" +dependencies = [ + "thiserror-impl", +] + +[[package]] +name = "thiserror-impl" +version = "1.0.56" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fa0faa943b50f3db30a20aa7e265dbc66076993efed8463e8de414e5d06d3471" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.48", +] + +[[package]] +name = "time" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f657ba42c3f86e7680e53c8cd3af8abbe56b5491790b46e22e19c0d57463583e" +dependencies = [ + "deranged", + "itoa", + "powerfmt", + "serde", + "time-core", + "time-macros", +] + +[[package]] +name = "time-core" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ef927ca75afb808a4d64dd374f00a2adf8d0fcff8e7b184af886c3c87ec4a3f3" + +[[package]] +name = "time-macros" +version = "0.2.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26197e33420244aeb70c3e8c78376ca46571bc4e701e4791c2cd9f57dcb3a43f" +dependencies = [ + "time-core", +] + +[[package]] +name = "tinyvec" +version = "1.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87cc5ceb3875bb20c2890005a4e226a4651264a5c75edb2421b52861a0a0cb50" +dependencies = [ + "tinyvec_macros", +] + +[[package]] +name = "tinyvec_macros" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" + +[[package]] +name = "tokio" +version = "1.35.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c89b4efa943be685f629b149f53829423f8f5531ea21249408e8e2f8671ec104" +dependencies = [ + "backtrace", + "bytes", + "libc", + "mio", + "parking_lot", + "pin-project-lite", + "signal-hook-registry", + "socket2", + "windows-sys 0.48.0", +] + +[[package]] +name = "tokio-io-timeout" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "30b74022ada614a1b4834de765f9bb43877f910cc8ce4be40e89042c9223a8bf" +dependencies = [ + "pin-project-lite", + "tokio", +] + +[[package]] +name = "tokio-native-tls" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbae76ab933c85776efabc971569dd6119c580d8f5d448769dec1764bf796ef2" +dependencies = [ + "native-tls", + "tokio", +] + +[[package]] +name = "tokio-rustls" +version = "0.24.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c28327cf380ac148141087fbfb9de9d7bd4e84ab5d2c28fbc911d753de8a7081" +dependencies = [ + "rustls", + "tokio", +] + +[[package]] +name = "tokio-stream" +version = "0.1.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "397c988d37662c7dda6d2208364a706264bf3d6138b11d436cbac0ad38832842" +dependencies = [ + "futures-core", + "pin-project-lite", + "tokio", +] + +[[package]] +name = "tokio-util" +version = "0.7.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5419f34732d9eb6ee4c3578b7989078579b7f039cbbb9ca2c4da015749371e15" +dependencies = [ + "bytes", + "futures-core", + "futures-sink", + "pin-project-lite", + "tokio", + "tracing", +] + +[[package]] +name = "tower" +version = "0.4.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8fa9be0de6cf49e536ce1851f987bd21a43b771b09473c3549a6c853db37c1c" +dependencies = [ + "futures-core", + "futures-util", + "pin-project", + "pin-project-lite", + "tokio", + "tokio-util", + "tower-layer", + "tower-service", + "tracing", +] + +[[package]] +name = "tower-http" +version = "0.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "61c5bb1d698276a2443e5ecfabc1008bf15a36c12e6a7176e7bf089ea9131140" +dependencies = [ + "bitflags 2.4.2", + "bytes", + "futures-core", + "futures-util", + "http", + "http-body", + "http-range-header", + "iri-string", + "pin-project-lite", + "tower", + "tower-layer", + "tower-service", + "tracing", +] + +[[package]] +name = "tower-layer" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c20c8dbed6283a09604c3e69b4b7eeb54e298b8a600d4d5ecb5ad39de609f1d0" + +[[package]] +name = "tower-service" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6bc1c9ce2b5135ac7f93c72918fc37feb872bdc6a5533a8b85eb4b86bfdae52" + +[[package]] +name = "tracing" +version = "0.1.40" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3523ab5a71916ccf420eebdf5521fcef02141234bbc0b8a49f2fdc4544364ef" +dependencies = [ + "log", + "pin-project-lite", + "tracing-attributes", + "tracing-core", +] + +[[package]] +name = "tracing-attributes" +version = "0.1.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.48", +] + +[[package]] +name = "tracing-core" +version = "0.1.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c06d3da6113f116aaee68e4d601191614c9053067f9ab7f6edbcb161237daa54" +dependencies = [ + "once_cell", +] + +[[package]] +name = "try-lock" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b" + +[[package]] +name = "typenum" +version = "1.17.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825" + +[[package]] +name = "unicode-bidi" +version = "0.3.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08f95100a766bf4f8f28f90d77e0a5461bbdb219042e7679bebe79004fed8d75" + +[[package]] +name = "unicode-ident" +version = "1.0.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" + +[[package]] +name = "unicode-normalization" +version = "0.1.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c5713f0fc4b5db668a2ac63cdb7bb4469d8c9fed047b1d0292cc7b0ce2ba921" +dependencies = [ + "tinyvec", +] + +[[package]] +name = "unicode-segmentation" +version = "1.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1dd624098567895118886609431a7c3b8f516e41d30e0643f03d94592a147e36" + +[[package]] +name = "unicode_categories" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "39ec24b3121d976906ece63c9daad25b85969647682eee313cb5779fdd69e14e" + +[[package]] +name = "untrusted" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" + +[[package]] +name = "url" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "31e6302e3bb753d46e83516cae55ae196fc0c309407cf11ab35cc51a4c2a4633" +dependencies = [ + "form_urlencoded", + "idna 0.5.0", + "percent-encoding", + "serde", +] + +[[package]] +name = "urlencoding" +version = "2.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "daf8dba3b7eb870caf1ddeed7bc9d2a049f3cfdfae7cb521b087cc33ae4c49da" + +[[package]] +name = "validator" +version = "0.16.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b92f40481c04ff1f4f61f304d61793c7b56ff76ac1469f1beb199b1445b253bd" +dependencies = [ + "idna 0.4.0", + "lazy_static", + "regex", + "serde", + "serde_derive", + "serde_json", + "url", + "validator_derive", +] + +[[package]] +name = "validator_derive" +version = "0.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bc44ca3088bb3ba384d9aecf40c6a23a676ce23e09bdaca2073d99c207f864af" +dependencies = [ + "if_chain", + "lazy_static", + "proc-macro-error", + "proc-macro2", + "quote", + "regex", + "syn 1.0.109", + "validator_types", +] + +[[package]] +name = "validator_types" +version = "0.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "111abfe30072511849c5910134e8baf8dc05de4c0e5903d681cbd5c9c4d611e3" +dependencies = [ + "proc-macro2", + "syn 1.0.109", +] + +[[package]] +name = "vcpkg" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" + +[[package]] +name = "version_check" +version = "0.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" + +[[package]] +name = "want" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bfa7760aed19e106de2c7c0b581b509f2f25d3dacaf737cb82ac61bc6d760b0e" +dependencies = [ + "try-lock", +] + +[[package]] +name = "wasi" +version = "0.11.0+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" + +[[package]] +name = "wasm-bindgen" +version = "0.2.90" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1223296a201415c7fad14792dbefaace9bd52b62d33453ade1c5b5f07555406" +dependencies = [ + "cfg-if", + "wasm-bindgen-macro", +] + +[[package]] +name = "wasm-bindgen-backend" +version = "0.2.90" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fcdc935b63408d58a32f8cc9738a0bffd8f05cc7c002086c6ef20b7312ad9dcd" +dependencies = [ + "bumpalo", + "log", + "once_cell", + "proc-macro2", + "quote", + "syn 2.0.48", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-futures" +version = "0.4.40" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bde2032aeb86bdfaecc8b261eef3cba735cc426c1f3a3416d1e0791be95fc461" +dependencies = [ + "cfg-if", + "js-sys", + "wasm-bindgen", + "web-sys", +] + +[[package]] +name = "wasm-bindgen-macro" +version = "0.2.90" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3e4c238561b2d428924c49815533a8b9121c664599558a5d9ec51f8a1740a999" +dependencies = [ + "quote", + "wasm-bindgen-macro-support", +] + +[[package]] +name = "wasm-bindgen-macro-support" +version = "0.2.90" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bae1abb6806dc1ad9e560ed242107c0f6c84335f1749dd4e8ddb012ebd5e25a7" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.48", + "wasm-bindgen-backend", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-shared" +version = "0.2.90" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4d91413b1c31d7539ba5ef2451af3f0b833a005eb27a631cec32bc0635a8602b" + +[[package]] +name = "web-sys" +version = "0.3.67" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "58cd2333b6e0be7a39605f0e255892fd7418a682d8da8fe042fe25128794d2ed" +dependencies = [ + "js-sys", + "wasm-bindgen", +] + +[[package]] +name = "whoami" +version = "1.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "22fc3756b8a9133049b26c7f61ab35416c130e8c09b660f5b3958b446f52cc50" + +[[package]] +name = "windows-core" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9" +dependencies = [ + "windows-targets 0.52.0", +] + +[[package]] +name = "windows-sys" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" +dependencies = [ + "windows-targets 0.48.5", +] + +[[package]] +name = "windows-sys" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" +dependencies = [ + "windows-targets 0.52.0", +] + +[[package]] +name = "windows-targets" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c" +dependencies = [ + "windows_aarch64_gnullvm 0.48.5", + "windows_aarch64_msvc 0.48.5", + "windows_i686_gnu 0.48.5", + "windows_i686_msvc 0.48.5", + "windows_x86_64_gnu 0.48.5", + "windows_x86_64_gnullvm 0.48.5", + "windows_x86_64_msvc 0.48.5", +] + +[[package]] +name = "windows-targets" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a18201040b24831fbb9e4eb208f8892e1f50a37feb53cc7ff887feb8f50e7cd" +dependencies = [ + "windows_aarch64_gnullvm 0.52.0", + "windows_aarch64_msvc 0.52.0", + "windows_i686_gnu 0.52.0", + "windows_i686_msvc 0.52.0", + "windows_x86_64_gnu 0.52.0", + "windows_x86_64_gnullvm 0.52.0", + "windows_x86_64_msvc 0.52.0", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb7764e35d4db8a7921e09562a0304bf2f93e0a51bfccee0bd0bb0b666b015ea" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbaa0368d4f1d2aaefc55b6fcfee13f41544ddf36801e793edbbfd7d7df075ef" + +[[package]] +name = "windows_i686_gnu" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" + +[[package]] +name = "windows_i686_gnu" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a28637cb1fa3560a16915793afb20081aba2c92ee8af57b4d5f28e4b3e7df313" + +[[package]] +name = "windows_i686_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" + +[[package]] +name = "windows_i686_msvc" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ffe5e8e31046ce6230cc7215707b816e339ff4d4d67c65dffa206fd0f7aa7b9a" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d6fa32db2bc4a2f5abeacf2b69f7992cd09dca97498da74a151a3132c26befd" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a657e1e9d3f514745a572a6846d3c7aa7dbe1658c056ed9c3344c4109a6949e" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dff9641d1cd4be8d1a070daf9e3773c5f67e78b4d9d42263020c057706765c04" + +[[package]] +name = "winreg" +version = "0.50.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "524e57b2c537c0f9b1e69f1965311ec12182b4122e45035b1508cd24d2adadb1" +dependencies = [ + "cfg-if", + "windows-sys 0.48.0", +] + +[[package]] +name = "zerocopy" +version = "0.7.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "74d4d3961e53fa4c9a25a8637fc2bfaf2595b3d3ae34875568a5cf64787716be" +dependencies = [ + "zerocopy-derive", +] + +[[package]] +name = "zerocopy-derive" +version = "0.7.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ce1b18ccd8e73a9321186f97e46f9f04b778851177567b1975109d26a08d2a6" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.48", +] + +[[package]] +name = "zeroize" +version = "1.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "525b4ec142c6b68a2d10f01f7bbf6755599ca3f81ea53b8431b7dd348f5fdb2d" + +[[package]] +name = "zstd" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bffb3309596d527cfcba7dfc6ed6052f1d39dfbd7c867aa2e865e4a449c10110" +dependencies = [ + "zstd-safe", +] + +[[package]] +name = "zstd-safe" +version = "7.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "43747c7422e2924c11144d5229878b98180ef8b06cca4ab5af37afc8a8d8ea3e" +dependencies = [ + "zstd-sys", +] + +[[package]] +name = "zstd-sys" +version = "2.0.9+zstd.1.5.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9e16efa8a874a0481a574084d34cc26fdb3b99627480f785888deb6386506656" +dependencies = [ + "cc", + "pkg-config", +] diff --git a/registry/Cargo.toml b/registry/Cargo.toml new file mode 100644 index 0000000..851c78d --- /dev/null +++ b/registry/Cargo.toml @@ -0,0 +1,29 @@ +[package] +name = "pesde-registry" +version = "0.1.0" +edition = "2021" + +[dependencies] +actix-web = "4.5.1" +actix-cors = "0.7.0" +actix-web-httpauth = "0.8.1" +actix-multipart = "0.6.1" +actix-multipart-derive = "0.6.1" +dotenvy = "0.15.7" +reqwest = { version = "0.11.24", features = ["json", "blocking"] } +rusty-s3 = "0.5.0" +serde = { version = "1.0.197", features = ["derive"] } +serde_json = "1.0.114" +serde_yaml = "0.9.32" +flate2 = "1.0.28" +tar = "0.4.40" +pesde = { path = ".." } +semver = "1.0.22" +git2 = "0.18.2" +thiserror = "1.0.57" +tantivy = "0.21.1" +log = "0.4.21" +pretty_env_logger = "0.5.0" +sentry = "0.32.2" +sentry-log = "0.32.2" +sentry-actix = "0.32.2" \ No newline at end of file diff --git a/registry/src/endpoints/mod.rs b/registry/src/endpoints/mod.rs new file mode 100644 index 0000000..d1cd92d --- /dev/null +++ b/registry/src/endpoints/mod.rs @@ -0,0 +1,8 @@ +use actix_web::web; + +pub mod packages; +pub mod search; + +pub fn configure(cfg: &mut web::ServiceConfig) { + cfg.configure(packages::configure); +} diff --git a/registry/src/endpoints/packages.rs b/registry/src/endpoints/packages.rs new file mode 100644 index 0000000..be879be --- /dev/null +++ b/registry/src/endpoints/packages.rs @@ -0,0 +1,208 @@ +use actix_multipart::form::{bytes::Bytes, MultipartForm}; +use actix_web::{get, post, web, HttpResponse, Responder}; +use flate2::read::GzDecoder; +use reqwest::StatusCode; +use rusty_s3::S3Action; +use tantivy::{doc, Term}; +use tar::Archive; + +use pesde::{ + dependencies::DependencySpecifier, index::Index, manifest::Manifest, package_name::PackageName, + IGNORED_FOLDERS, MANIFEST_FILE_NAME, +}; + +use crate::{commit_signature, errors, AppState, UserId, S3_EXPIRY}; + +#[derive(MultipartForm)] +struct CreateForm { + #[multipart(limit = "4 MiB")] + tarball: Bytes, +} + +#[post("/packages")] +async fn create( + form: MultipartForm, + app_state: web::Data, + user_id: web::ReqData, +) -> Result { + let bytes = form.tarball.data.as_ref().to_vec(); + let mut decoder = GzDecoder::new(bytes.as_slice()); + let mut archive = Archive::new(&mut decoder); + + let archive_entries = archive.entries()?.filter_map(|e| e.ok()); + + let mut manifest = None; + + for mut e in archive_entries { + let Ok(path) = e.path() else { + return Ok(HttpResponse::BadRequest().json(errors::ErrorResponse { + error: "Attached file contains non-UTF-8 path".to_string(), + })); + }; + + let Some(path) = path.as_os_str().to_str() else { + return Ok(HttpResponse::BadRequest().json(errors::ErrorResponse { + error: "Attached file contains non-UTF-8 path".to_string(), + })); + }; + + match path { + MANIFEST_FILE_NAME => { + if !e.header().entry_type().is_file() { + continue; + } + + let received_manifest: Manifest = + serde_yaml::from_reader(&mut e).map_err(errors::Errors::UserYaml)?; + + manifest = Some(received_manifest); + } + path => { + if e.header().entry_type().is_file() { + continue; + } + + if IGNORED_FOLDERS.contains(&path) { + return Ok(HttpResponse::BadRequest().json(errors::ErrorResponse { + error: format!("Attached file contains forbidden directory {}", path), + })); + } + } + } + } + + let Some(manifest) = manifest else { + return Ok(HttpResponse::BadRequest().json(errors::ErrorResponse { + error: format!("Attached file doesn't contain {MANIFEST_FILE_NAME}"), + })); + }; + + let (scope, name) = manifest.name.parts(); + + { + let mut index = app_state.index.lock().unwrap(); + let config = index.config()?; + + for (dependency, _) in manifest.dependencies().iter() { + match dependency { + DependencySpecifier::Git(_) => { + if !config.git_allowed { + return Ok(HttpResponse::BadRequest().json(errors::ErrorResponse { + error: "Git dependencies are not allowed on this registry".to_string(), + })); + } + } + DependencySpecifier::Registry(registry) => { + if index.package(®istry.name).unwrap().is_none() { + return Ok(HttpResponse::BadRequest().json(errors::ErrorResponse { + error: format!("Dependency {} not found", registry.name), + })); + } + } + }; + } + + let success = index.create_package_version(&manifest, &user_id.0)?; + + if !success { + return Ok(HttpResponse::BadRequest().json(errors::ErrorResponse { + error: format!( + "Version {} of {} already exists", + manifest.version, manifest.name + ), + })); + } + + index.commit_and_push( + &format!("Add version {}@{}", manifest.name, manifest.version), + &commit_signature(), + )?; + } + + { + let mut search_writer = app_state.search_writer.lock().unwrap(); + let schema = search_writer.index().schema(); + let name_field = schema.get_field("name").unwrap(); + + search_writer.delete_term(Term::from_field_text( + name_field, + &manifest.name.to_string(), + )); + + search_writer.add_document( + doc!( + name_field => manifest.name.to_string(), + schema.get_field("version").unwrap() => manifest.version.to_string(), + schema.get_field("description").unwrap() => manifest.description.unwrap_or_default(), + ) + ).unwrap(); + + search_writer.commit().unwrap(); + } + + let url = app_state + .s3_bucket + .put_object( + Some(&app_state.s3_credentials), + &*format!("{scope}-{name}-{}.tar.gz", manifest.version), + ) + .sign(S3_EXPIRY); + + app_state.reqwest_client.put(url).body(bytes).send().await?; + + Ok(HttpResponse::Ok().body(format!( + "Successfully published {}@{}", + manifest.name, manifest.version + ))) +} + +#[get("/packages/{author_name}/{package_name}/{version}")] +async fn get( + app_state: web::Data, + path: web::Path<(String, String, String)>, +) -> Result { + let (scope, name, version) = path.into_inner(); + + let package_name = PackageName::new(&scope, &name)?; + + { + let index = app_state.index.lock().unwrap(); + + if !index.package(&package_name)?.is_some() { + return Ok(HttpResponse::NotFound().finish()); + } + } + + let url = app_state + .s3_bucket + .get_object( + Some(&app_state.s3_credentials), + &*format!("{scope}-{name}-{version}.tar.gz"), + ) + .sign(S3_EXPIRY); + + let response = match app_state + .reqwest_client + .get(url) + .send() + .await? + .error_for_status() + { + Ok(response) => response, + Err(e) => { + if let Some(status) = e.status() { + if status == StatusCode::NOT_FOUND { + return Ok(HttpResponse::NotFound().finish()); + } + } + + return Err(e.into()); + } + }; + + Ok(HttpResponse::Ok().body(response.bytes().await?)) +} + +pub fn configure(cfg: &mut web::ServiceConfig) { + cfg.service(create).service(get); +} diff --git a/registry/src/endpoints/search.rs b/registry/src/endpoints/search.rs new file mode 100644 index 0000000..1aedb23 --- /dev/null +++ b/registry/src/endpoints/search.rs @@ -0,0 +1,56 @@ +use actix_web::{get, web, Responder}; +use serde::Deserialize; +use serde_json::{json, Value}; + +use crate::{errors, AppState}; + +#[derive(Deserialize)] +struct Query { + query: String, +} + +#[get("/search")] +async fn search( + app_state: web::Data, + query: web::Query, +) -> Result { + let searcher = app_state.search_reader.searcher(); + let schema = searcher.schema(); + + let name = schema.get_field("name").unwrap(); + let version = schema.get_field("version").unwrap(); + let description = schema.get_field("description").unwrap(); + + let query = query.query.trim(); + + if query.is_empty() { + return Ok(web::Json(vec![])); + } + + let query_parser = + tantivy::query::QueryParser::for_index(&searcher.index(), vec![name, description]); + let query = query_parser.parse_query(&query)?; + + let top_docs = searcher + .search(&query, &tantivy::collector::TopDocs::with_limit(10)) + .unwrap(); + + Ok(web::Json( + top_docs + .into_iter() + .map(|(_, doc_address)| { + let retrieved_doc = searcher.doc(doc_address).unwrap(); + + json!({ + "name": retrieved_doc.get_first(name).unwrap().as_text().unwrap(), + "version": retrieved_doc.get_first(version).unwrap().as_text().unwrap(), + "description": retrieved_doc.get_first(description).unwrap().as_text().unwrap(), + }) + }) + .collect::>(), + )) +} + +pub fn configure(cfg: &mut web::ServiceConfig) { + cfg.service(search); +} diff --git a/registry/src/errors.rs b/registry/src/errors.rs new file mode 100644 index 0000000..f84f70e --- /dev/null +++ b/registry/src/errors.rs @@ -0,0 +1,71 @@ +use actix_web::{HttpResponse, ResponseError}; +use log::error; +use serde::Serialize; +use thiserror::Error; + +#[derive(Serialize)] +pub struct ErrorResponse { + pub error: String, +} + +#[derive(Debug, Error)] +pub enum Errors { + #[error("io error")] + Io(#[from] std::io::Error), + + #[error("user yaml error")] + UserYaml(serde_yaml::Error), + + #[error("reqwest error")] + Reqwest(#[from] reqwest::Error), + + #[error("package name invalid")] + PackageName(#[from] pesde::package_name::PackageNameValidationError), + + #[error("config error")] + Config(#[from] pesde::index::ConfigError), + + #[error("create package version error")] + CreatePackageVersion(#[from] pesde::index::CreatePackageVersionError), + + #[error("commit and push error")] + CommitAndPush(#[from] pesde::index::CommitAndPushError), + + #[error("index package error")] + IndexPackage(#[from] pesde::index::IndexPackageError), + + #[error("error parsing query")] + QueryParser(#[from] tantivy::query::QueryParserError), +} + +impl ResponseError for Errors { + fn error_response(&self) -> HttpResponse { + match self { + Errors::UserYaml(_) | Errors::PackageName(_) | Errors::QueryParser(_) => {} + Errors::CreatePackageVersion(err) => match err { + pesde::index::CreatePackageVersionError::MissingScopeOwnership => { + return HttpResponse::Unauthorized().json(ErrorResponse { + error: "You do not have permission to publish this scope".to_string(), + }); + } + _ => error!("{err:?}"), + }, + err => { + error!("{err:?}"); + } + } + + match self { + Errors::UserYaml(err) => HttpResponse::BadRequest().json(ErrorResponse { + error: format!("Error parsing YAML file: {}", err.to_string()), + }), + Errors::PackageName(err) => HttpResponse::BadRequest().json(ErrorResponse { + error: format!("Invalid package name: {}", err.to_string()), + }), + Errors::QueryParser(err) => HttpResponse::BadRequest().json(ErrorResponse { + error: format!("Error parsing query: {}", err.to_string()), + }), + _ => HttpResponse::InternalServerError().finish(), + } + } +} diff --git a/registry/src/main.rs b/registry/src/main.rs new file mode 100644 index 0000000..18a1c6f --- /dev/null +++ b/registry/src/main.rs @@ -0,0 +1,272 @@ +use std::{fs::read_dir, sync::Mutex, time::Duration}; + +use actix_cors::Cors; +use actix_web::{ + dev::ServiceRequest, + error::ErrorUnauthorized, + middleware::{Compress, Condition}, + rt::System, + web, App, Error, HttpMessage, HttpServer, +}; +use actix_web_httpauth::{extractors::bearer::BearerAuth, middleware::HttpAuthentication}; +use dotenvy::dotenv; +use git2::{Cred, Signature}; +use log::info; +use reqwest::{header::AUTHORIZATION, Client}; +use rusty_s3::{Bucket, Credentials, UrlStyle}; +use tantivy::{doc, IndexReader, IndexWriter}; + +use pesde::{ + index::{GitIndex, IndexFile}, + package_name::PackageName, +}; + +mod endpoints; +mod errors; + +const S3_EXPIRY: Duration = Duration::from_secs(60 * 60); + +struct AppState { + s3_bucket: Bucket, + s3_credentials: Credentials, + reqwest_client: Client, + index: Mutex, + + search_reader: IndexReader, + search_writer: Mutex, +} + +macro_rules! get_env { + ($name:expr, "p") => { + std::env::var($name) + .expect(concat!("Environment variable `", $name, "` must be set")) + .parse() + .expect(concat!( + "Environment variable `", + $name, + "` must be a valid value" + )) + }; + ($name:expr) => { + std::env::var($name).expect(concat!("Environment variable `", $name, "` must be set")) + }; + ($name:expr, $default:expr, "p") => { + std::env::var($name) + .unwrap_or($default.to_string()) + .parse() + .expect(concat!( + "Environment variable `", + $name, + "` must a valid value" + )) + }; + ($name:expr, $default:expr) => { + std::env::var($name).unwrap_or($default.to_string()) + }; +} + +pub fn commit_signature<'a>() -> Signature<'a> { + Signature::now( + &get_env!("COMMITTER_GIT_NAME"), + &get_env!("COMMITTER_GIT_EMAIL"), + ) + .unwrap() +} + +#[derive(Debug, Clone)] +pub struct UserId(pub u64); + +async fn validator( + req: ServiceRequest, + credentials: BearerAuth, +) -> Result { + let token = credentials.token(); + let app_state = req.app_data::>().unwrap(); + + let Ok(user_info) = app_state + .reqwest_client + .get("https://api.github.com/user") + .header(AUTHORIZATION, format!("Bearer {}", token)) + .send() + .await + .map(|r| r.json::()) + else { + return Err((ErrorUnauthorized("Failed to fetch user info"), req)); + }; + + let Ok(user_info) = user_info.await else { + return Err((ErrorUnauthorized("Failed to parse user info"), req)); + }; + + let Some(id) = user_info["id"].as_u64() else { + return Err((ErrorUnauthorized("Failed to fetch user info"), req)); + }; + + req.extensions_mut().insert(UserId(id)); + + Ok(req) +} + +fn search_index(index: &GitIndex) -> (IndexReader, IndexWriter) { + let mut schema_builder = tantivy::schema::SchemaBuilder::new(); + let name = + schema_builder.add_text_field("name", tantivy::schema::TEXT | tantivy::schema::STORED); + let version = + schema_builder.add_text_field("version", tantivy::schema::TEXT | tantivy::schema::STORED); + let description = schema_builder.add_text_field( + "description", + tantivy::schema::TEXT | tantivy::schema::STORED, + ); + + let search_index = tantivy::Index::create_in_ram(schema_builder.build()); + let search_reader = search_index + .reader_builder() + .reload_policy(tantivy::ReloadPolicy::OnCommit) + .try_into() + .unwrap(); + let mut search_writer = search_index.writer(50_000_000).unwrap(); + + for entry in read_dir(index.path()).unwrap() { + let entry = entry.unwrap(); + let path = entry.path(); + + if !path.is_dir() || path.file_name().unwrap() == ".git" { + continue; + } + + let scope = path.file_name().unwrap().to_str().unwrap(); + + for entry in read_dir(&path).unwrap() { + let entry = entry.unwrap(); + let path = entry.path(); + + if !path.is_file() || path.extension().is_some() { + continue; + } + + let package = path.file_name().unwrap().to_str().unwrap(); + + let package_name = PackageName::new(scope, package).unwrap(); + let entries: IndexFile = + serde_yaml::from_slice(&std::fs::read(&path).unwrap()).unwrap(); + let entry = entries + .iter() + .max_by(|a, b| a.version.cmp(&b.version)) + .unwrap() + .clone(); + + search_writer + .add_document(doc!( + name => package_name.to_string(), + version => entry.version.to_string(), + description => entry.description.unwrap_or_default() + )) + .unwrap(); + } + } + + search_writer.commit().unwrap(); + + (search_reader, search_writer) +} + +fn main() -> std::io::Result<()> { + dotenv().ok(); + + let sentry_url = std::env::var("SENTRY_URL").ok(); + let with_sentry = sentry_url.is_some(); + + let mut log_builder = pretty_env_logger::formatted_builder(); + log_builder.parse_env(pretty_env_logger::env_logger::Env::default().default_filter_or("info")); + + if with_sentry { + let logger = sentry_log::SentryLogger::with_dest(log_builder.build()); + log::set_boxed_logger(Box::new(logger)).unwrap(); + log::set_max_level(log::LevelFilter::Info); + } else { + log_builder.try_init().unwrap(); + } + + let _guard = if let Some(sentry_url) = sentry_url { + std::env::set_var("RUST_BACKTRACE", "1"); + + Some(sentry::init(( + sentry_url, + sentry::ClientOptions { + release: sentry::release_name!(), + ..Default::default() + }, + ))) + } else { + None + }; + + let address = get_env!("ADDRESS", "127.0.0.1"); + let port: u16 = get_env!("PORT", "8080", "p"); + + let current_dir = std::env::current_dir().unwrap(); + + let index = GitIndex::new( + current_dir.join("cache"), + &get_env!("INDEX_REPO_URL"), + Some(Box::new(|| { + Box::new(|_, _, _| { + let username = get_env!("GITHUB_USERNAME"); + let pat = get_env!("GITHUB_PAT"); + + Cred::userpass_plaintext(&username, &pat) + }) + })), + ); + index.refresh().expect("failed to refresh index"); + + let (search_reader, search_writer) = search_index(&index); + + let app_data = web::Data::new(AppState { + s3_bucket: Bucket::new( + get_env!("S3_ENDPOINT", "p"), + UrlStyle::Path, + get_env!("S3_BUCKET_NAME"), + get_env!("S3_REGION"), + ) + .unwrap(), + s3_credentials: Credentials::new(get_env!("S3_ACCESS_KEY"), get_env!("S3_SECRET_KEY")), + reqwest_client: Client::builder() + .user_agent(concat!( + env!("CARGO_PKG_NAME"), + "/", + env!("CARGO_PKG_VERSION") + )) + .build() + .unwrap(), + index: Mutex::new(index), + + search_reader, + search_writer: Mutex::new(search_writer), + }); + + info!("listening on {address}:{port}"); + + System::new().block_on(async move { + HttpServer::new(move || { + App::new() + .wrap(Condition::new(with_sentry, sentry_actix::Sentry::new())) + .wrap(Cors::permissive()) + .wrap(Compress::default()) + .app_data(app_data.clone()) + .route("/", web::get().to(|| async { env!("CARGO_PKG_VERSION") })) + .service( + web::scope("/v0") + .configure(endpoints::search::configure) + .service( + web::scope("") + .wrap(HttpAuthentication::with_fn(validator)) + .configure(endpoints::configure), + ), + ) + }) + .bind((address, port))? + .run() + .await + }) +} diff --git a/rust-toolchain.toml b/rust-toolchain.toml new file mode 100644 index 0000000..31578d3 --- /dev/null +++ b/rust-toolchain.toml @@ -0,0 +1,2 @@ +[toolchain] +channel = "stable" \ No newline at end of file diff --git a/src/cli/auth.rs b/src/cli/auth.rs new file mode 100644 index 0000000..419ed21 --- /dev/null +++ b/src/cli/auth.rs @@ -0,0 +1,110 @@ +use clap::Subcommand; +use pesde::index::Index; +use reqwest::{header::AUTHORIZATION, Url}; + +use crate::{send_request, CliParams}; + +#[derive(Subcommand)] +pub enum AuthCommand { + /// Logs in to the registry + Login, + /// Logs out from the registry + Logout, +} + +pub fn auth_command(cmd: AuthCommand, params: CliParams) -> anyhow::Result<()> { + let index_config = params.index.config()?; + + match cmd { + AuthCommand::Login => { + let response = send_request!(params.reqwest_client.post(Url::parse_with_params( + "https://github.com/login/device/code", + &[("client_id", index_config.github_oauth_client_id.as_str())], + )?)) + .json::()?; + + println!( + "go to {} and enter the code `{}`", + response["verification_uri"], response["user_code"] + ); + + let mut time_left = response["expires_in"] + .as_i64() + .ok_or(anyhow::anyhow!("couldn't get expires_in"))?; + let interval = std::time::Duration::from_secs( + response["interval"] + .as_u64() + .ok_or(anyhow::anyhow!("couldn't get interval"))?, + ); + let device_code = response["device_code"] + .as_str() + .ok_or(anyhow::anyhow!("couldn't get device_code"))?; + + while time_left > 0 { + std::thread::sleep(interval); + time_left -= interval.as_secs() as i64; + let response = send_request!(params.reqwest_client.post(Url::parse_with_params( + "https://github.com/login/oauth/access_token", + &[ + ("client_id", index_config.github_oauth_client_id.as_str()), + ("device_code", device_code), + ("grant_type", "urn:ietf:params:oauth:grant-type:device_code") + ], + )?)) + .json::()?; + + match response + .get("error") + .map(|s| { + s.as_str() + .ok_or(anyhow::anyhow!("couldn't get error as string")) + }) + .unwrap_or(Ok(""))? + { + "authorization_pending" => continue, + "slow_down" => { + std::thread::sleep(std::time::Duration::from_secs(5)); + continue; + } + "expired_token" => { + break; + } + "access_denied" => { + anyhow::bail!("access denied, re-run the login command"); + } + _ => (), + } + + if response.get("access_token").is_some() { + let access_token = response["access_token"] + .as_str() + .ok_or(anyhow::anyhow!("couldn't get access_token"))?; + + params.api_token_entry.set_password(access_token)?; + + let response = send_request!(params + .reqwest_client + .get("https://api.github.com/user") + .header(AUTHORIZATION, format!("Bearer {access_token}"))) + .json::()?; + + let login = response["login"] + .as_str() + .ok_or(anyhow::anyhow!("couldn't get login"))?; + + println!("you're now logged in as {login}"); + return Ok(()); + } + } + + anyhow::bail!("code expired, please re-run the login command"); + } + AuthCommand::Logout => { + params.api_token_entry.delete_password()?; + + println!("you're now logged out"); + } + } + + Ok(()) +} diff --git a/src/cli/config.rs b/src/cli/config.rs new file mode 100644 index 0000000..c09689d --- /dev/null +++ b/src/cli/config.rs @@ -0,0 +1,66 @@ +use std::path::PathBuf; + +use clap::Subcommand; + +use crate::{CliConfig, CliParams}; + +#[derive(Subcommand)] +pub enum ConfigCommand { + /// Sets the index repository URL + SetIndexRepo { + #[clap(value_name = "URL")] + url: String, + }, + /// Gets the index repository URL + GetIndexRepo, + + /// Sets the cache directory + SetCacheDir { + #[clap(value_name = "DIRECTORY")] + directory: Option, + }, + /// Gets the cache directory + GetCacheDir, +} + +pub fn config_command(cmd: ConfigCommand, params: CliParams) -> anyhow::Result<()> { + match cmd { + ConfigCommand::SetIndexRepo { url } => { + let cli_config = CliConfig { + index_repo_url: url.clone(), + ..params.cli_config + }; + + cli_config.write(¶ms.directories)?; + + println!("index repository url set to: `{url}`"); + } + ConfigCommand::GetIndexRepo => { + println!( + "current index repository url: `{}`", + params.cli_config.index_repo_url + ); + } + ConfigCommand::SetCacheDir { directory } => { + let cli_config = CliConfig { + cache_dir: directory, + ..params.cli_config + }; + + cli_config.write(¶ms.directories)?; + + println!( + "cache directory set to: `{}`", + cli_config.cache_dir(¶ms.directories).display() + ); + } + ConfigCommand::GetCacheDir => { + println!( + "current cache directory: `{}`", + params.cli_config.cache_dir(¶ms.directories).display() + ); + } + } + + Ok(()) +} diff --git a/src/cli/mod.rs b/src/cli/mod.rs new file mode 100644 index 0000000..7a5ccd6 --- /dev/null +++ b/src/cli/mod.rs @@ -0,0 +1,3 @@ +pub mod auth; +pub mod config; +pub mod root; diff --git a/src/cli/root.rs b/src/cli/root.rs new file mode 100644 index 0000000..386cd41 --- /dev/null +++ b/src/cli/root.rs @@ -0,0 +1,281 @@ +use std::{ + fs::{create_dir_all, read, remove_dir_all, write}, + time::Duration, +}; + +use flate2::{write::GzEncoder, Compression}; +use futures_executor::block_on; +use ignore::{overrides::OverrideBuilder, WalkBuilder}; +use log::debug; +use lune::Runtime; +use reqwest::{header::AUTHORIZATION, Url}; +use semver::Version; +use serde_json::Value; +use tar::Builder as TarBuilder; + +use pesde::{ + dependencies::PackageRef, + index::{GitIndex, Index}, + manifest::Manifest, + package_name::PackageName, + patches::{create_patch, setup_patches_repo}, + project::{InstallOptions, Project}, + DEV_PACKAGES_FOLDER, IGNORED_FOLDERS, PACKAGES_FOLDER, PATCHES_FOLDER, SERVER_PACKAGES_FOLDER, +}; + +use crate::{send_request, CliParams, Command}; + +pub const MAX_ARCHIVE_SIZE: usize = 4 * 1024 * 1024; + +fn get_project(params: &CliParams) -> anyhow::Result> { + Project::from_path( + ¶ms.cwd, + params.cli_config.cache_dir(¶ms.directories), + params.index.clone(), + params.api_token_entry.get_password().ok(), + ) + .map_err(Into::into) +} + +pub fn root_command(cmd: Command, params: CliParams) -> anyhow::Result<()> { + match cmd { + Command::Install { locked } => { + let project = get_project(¶ms)?; + + for packages_folder in &[PACKAGES_FOLDER, DEV_PACKAGES_FOLDER, SERVER_PACKAGES_FOLDER] { + if let Err(e) = remove_dir_all(¶ms.cwd.join(packages_folder)) { + if e.kind() != std::io::ErrorKind::NotFound { + return Err(e.into()); + } else { + debug!("no {packages_folder} folder found, skipping removal"); + } + }; + } + + let resolved_versions_map = project.manifest().dependency_tree(&project, locked)?; + + let download_job = project.download(&resolved_versions_map)?; + let bar = params.multi.add( + indicatif::ProgressBar::new(resolved_versions_map.len() as u64) + .with_style(indicatif::ProgressStyle::default_bar().template( + "{msg} {bar:40.208/166} {pos}/{len} {percent}% {elapsed_precise}", + )?) + .with_message("Downloading packages"), + ); + bar.enable_steady_tick(Duration::from_millis(100)); + + while let Ok(result) = download_job.progress().recv() { + result?; + bar.inc(1); + } + + bar.finish_with_message("done"); + + project.install( + InstallOptions::new() + .locked(locked) + .auto_download(false) + .resolved_versions_map(resolved_versions_map), + )?; + } + Command::Run { package, args } => { + let project = get_project(¶ms)?; + + let name: PackageName = package.parse()?; + + let lockfile = project + .lockfile()? + .ok_or(anyhow::anyhow!("lockfile not found"))?; + + let (_, resolved_pkg) = lockfile + .get(&name) + .and_then(|versions| versions.iter().find(|(_, pkg_ref)| pkg_ref.is_root)) + .ok_or(anyhow::anyhow!("package not found in lockfile"))?; + + if !resolved_pkg.is_root { + anyhow::bail!("package is not a root package"); + } + + let pkg_path = resolved_pkg.directory(project.path()).1; + let manifest = Manifest::from_path(&pkg_path)?; + + let Some(bin_path) = manifest.exports.bin else { + anyhow::bail!("no bin found in package"); + }; + + let absolute_bin_path = bin_path.to_path(pkg_path); + + let mut runtime = Runtime::new().with_args(args); + + block_on(runtime.run( + resolved_pkg.pkg_ref.name().to_string(), + &read(absolute_bin_path)?, + ))?; + } + Command::Search { query } => { + let config = params.index.config()?; + let api_url = config.api(); + + let response = send_request!(params.reqwest_client.get(Url::parse_with_params( + &format!("{}/v0/search", api_url), + &query.map_or_else(Vec::new, |q| vec![("query", q)]) + )?)) + .json::()?; + + for package in response.as_array().unwrap() { + println!( + "{}@{}{}", + package["name"].as_str().unwrap(), + package["version"].as_str().unwrap(), + package["description"] + .as_str() + .map(|d| if d.is_empty() { + d.to_string() + } else { + format!("\n{}\n", d) + }) + .unwrap() + ); + } + } + Command::Publish => { + let project = get_project(¶ms)?; + + if project.manifest().private { + anyhow::bail!("package is private, cannot publish"); + } + + let encoder = GzEncoder::new(vec![], Compression::default()); + let mut archive = TarBuilder::new(encoder); + + let mut walk_builder = WalkBuilder::new(¶ms.cwd); + walk_builder.add_custom_ignore_filename(".pesdeignore"); + let mut overrides = OverrideBuilder::new(¶ms.cwd); + + for packages_folder in IGNORED_FOLDERS { + overrides.add(&format!("!{}", packages_folder))?; + } + + walk_builder.overrides(overrides.build()?); + + for entry in walk_builder.build() { + let entry = entry?; + let path = entry.path(); + let relative_path = path.strip_prefix(¶ms.cwd)?; + let entry_type = entry + .file_type() + .ok_or(anyhow::anyhow!("failed to get file type"))?; + + if relative_path.as_os_str().is_empty() { + continue; + } + + if entry_type.is_file() { + archive.append_path_with_name(path, relative_path)?; + } else if entry_type.is_dir() { + archive.append_dir(relative_path, path)?; + } + } + + let archive = archive.into_inner()?.finish()?; + + if archive.len() > MAX_ARCHIVE_SIZE { + anyhow::bail!( + "archive is too big ({} bytes), max {MAX_ARCHIVE_SIZE}. aborting...", + archive.len() + ); + } + + let part = reqwest::blocking::multipart::Part::bytes(archive) + .file_name("tarball.tar.gz") + .mime_str("application/gzip")?; + + let mut request = params + .reqwest_client + .post(format!("{}/v0/packages", project.index().config()?.api())) + .multipart(reqwest::blocking::multipart::Form::new().part("tarball", part)); + + if let Some(token) = project.registry_auth_token() { + request = request.header(AUTHORIZATION, format!("Bearer {token}")); + } else { + request = request.header(AUTHORIZATION, ""); + } + + println!("{}", send_request!(request).text()?); + } + Command::Patch { package } => { + let project = get_project(¶ms)?; + + let (name, version) = package + .split_once('@') + .ok_or(anyhow::anyhow!("Malformed package name"))?; + let name: PackageName = name.parse()?; + let version = Version::parse(version)?; + + let lockfile = project + .lockfile()? + .ok_or(anyhow::anyhow!("lockfile not found"))?; + + let resolved_pkg = lockfile + .get(&name) + .and_then(|versions| versions.get(&version)) + .ok_or(anyhow::anyhow!("package not found in lockfile"))?; + + let dir = params.directories.data_dir().join("patches").join(format!( + "{}_{}", + name.escaped(), + version + )); + + if dir.exists() { + anyhow::bail!( + "patch already exists. remove the directory {} to create a new patch", + dir.display() + ); + } + + create_dir_all(&dir)?; + + resolved_pkg.pkg_ref.download(&project, &dir)?; + match resolved_pkg.pkg_ref { + PackageRef::Git(_) => {} + _ => { + setup_patches_repo(&dir)?; + } + } + + println!("done! modify the files in {} and run `{} patch-commit ` to commit the changes", dir.display(), env!("CARGO_BIN_NAME")); + } + Command::PatchCommit { dir } => { + let project = get_project(¶ms)?; + + let manifest = Manifest::from_path(&dir)?; + let patch_path = project.path().join(PATCHES_FOLDER).join(format!( + "{}@{}.patch", + manifest.name.escaped(), + manifest.version + )); + + if patch_path.exists() { + anyhow::bail!( + "patch already exists. remove the file {} to create a new patch", + patch_path.display() + ); + } + + let patches = create_patch(&dir)?; + + write(&patch_path, patches)?; + + remove_dir_all(&dir)?; + + println!( + "done! to apply the patch, run `{} install`", + env!("CARGO_BIN_NAME") + ); + } + _ => unreachable!(), + } + + Ok(()) +} diff --git a/src/dependencies/git.rs b/src/dependencies/git.rs new file mode 100644 index 0000000..4415eea --- /dev/null +++ b/src/dependencies/git.rs @@ -0,0 +1,161 @@ +use std::{fs::create_dir_all, path::Path}; + +use git2::{build::RepoBuilder, Repository}; +use log::{debug, warn}; +use semver::Version; +use serde::{Deserialize, Serialize}; +use thiserror::Error; + +use crate::{ + index::{remote_callbacks, Index}, + manifest::{Manifest, ManifestReadError, Realm}, + package_name::PackageName, + project::Project, +}; + +/// A dependency of a package that can be downloaded from a git repository +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, Hash)] +#[serde(deny_unknown_fields)] +pub struct GitDependencySpecifier { + /// The URL of the git repository (can be in the form of `owner/repo`, in which case it will default to GitHub) + pub repo: String, + /// The revision of the git repository to use + pub rev: String, + /// The realm of the package + pub realm: Option, +} + +/// A reference to a package that can be downloaded from a git repository +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, Hash)] +#[serde(deny_unknown_fields)] +pub struct GitPackageRef { + /// The name of the package + pub name: PackageName, + /// The version of the package + pub version: Version, + /// The URL of the git repository + pub repo_url: String, + /// The revision of the git repository to use + pub rev: String, +} + +/// An error that occurred while downloading a git repository +#[derive(Debug, Error)] +pub enum GitDownloadError { + /// An error that occurred while interacting with git + #[error("error interacting with git")] + Git(#[from] git2::Error), + + /// An error that occurred while interacting with the file system + #[error("error interacting with the file system")] + Io(#[from] std::io::Error), + + /// An error that occurred while reading the manifest of the git repository + #[error("error reading manifest")] + ManifestRead(#[from] ManifestReadError), +} + +impl GitDependencySpecifier { + pub(crate) fn resolve( + &self, + project: &Project, + ) -> Result<(Manifest, String, String), GitDownloadError> { + debug!("resolving git dependency {}", self.repo); + + // should also work with ssh urls + let is_url = self.repo.contains(':'); + + let repo_name = { + if !is_url { + self.repo.to_string() + } else { + let parts: Vec<&str> = self.repo.split('/').collect(); + format!( + "{}/{}", + parts[parts.len() - 2], + parts[parts.len() - 1].trim_end_matches(".git") + ) + } + }; + + if is_url { + debug!("resolved git repository name to: {}", &repo_name); + } else { + debug!("assuming git repository is a name: {}", &repo_name); + } + + let repo_url = { + if !is_url { + format!("https://github.com/{}.git", &self.repo) + } else { + self.repo.to_string() + } + }; + + if is_url { + debug!("assuming git repository is a url: {}", &repo_url); + } else { + debug!("resolved git repository url to: {}", &repo_url); + } + + let dest = project + .cache_dir() + .join("git") + .join(repo_name.replace('/', "_")) + .join(&self.rev); + + let repo = if !dest.exists() { + create_dir_all(&dest)?; + + let mut fetch_options = git2::FetchOptions::new(); + fetch_options.remote_callbacks(remote_callbacks(project.index())); + + RepoBuilder::new() + .fetch_options(fetch_options) + .clone(&repo_url, &dest)? + } else { + Repository::open(&dest)? + }; + + let obj = repo.revparse_single(&self.rev)?; + debug!("resolved git revision {} to: {}", self.rev, obj.id()); + + repo.reset(&obj, git2::ResetType::Hard, None)?; + + Ok(( + Manifest::from_path(dest)?, + repo_url.to_string(), + obj.id().to_string(), + )) + } +} + +impl GitPackageRef { + /// Downloads the package to the specified destination + pub fn download, I: Index>( + &self, + project: &Project, + dest: P, + ) -> Result<(), GitDownloadError> { + let mut fetch_options = git2::FetchOptions::new(); + fetch_options.remote_callbacks(remote_callbacks(project.index())); + + let repo = RepoBuilder::new() + .fetch_options(fetch_options) + .clone(&self.repo_url, dest.as_ref())?; + + let obj = repo.revparse_single(&self.rev)?; + + if self.rev != obj.id().to_string() { + warn!( + "git package ref {} resolved to a different revision: {}. this shouldn't happen", + self.rev, + obj.id() + ); + } + + repo.reset(&obj, git2::ResetType::Hard, None)?; + + Ok(()) + } +} diff --git a/src/dependencies/mod.rs b/src/dependencies/mod.rs new file mode 100644 index 0000000..5adc5cb --- /dev/null +++ b/src/dependencies/mod.rs @@ -0,0 +1,182 @@ +use log::debug; +use std::{fmt::Display, fs::create_dir_all, path::Path}; + +use semver::Version; +use serde::{de::IntoDeserializer, Deserialize, Deserializer, Serialize}; +use thiserror::Error; + +use crate::{ + dependencies::{ + git::{GitDependencySpecifier, GitPackageRef}, + registry::{RegistryDependencySpecifier, RegistryPackageRef}, + resolution::ResolvedVersionsMap, + }, + index::Index, + manifest::Realm, + multithread::MultithreadedJob, + package_name::PackageName, + project::{InstallProjectError, Project}, +}; + +/// Git dependency related stuff +pub mod git; +/// Registry dependency related stuff +pub mod registry; +/// Resolution +pub mod resolution; + +// To improve developer experience, we resolve the type of the dependency specifier with a custom deserializer, so that the user doesn't have to specify the type of the dependency +/// A dependency of a package +#[derive(Serialize, Debug, Clone, PartialEq, Eq, Hash)] +#[serde(untagged)] +pub enum DependencySpecifier { + /// A dependency that can be downloaded from a registry + Registry(RegistryDependencySpecifier), + /// A dependency that can be downloaded from a git repository + Git(GitDependencySpecifier), +} + +impl DependencySpecifier { + /// Gets the name (or repository) of the specifier + pub fn name(&self) -> String { + match self { + DependencySpecifier::Registry(registry) => registry.name.to_string(), + DependencySpecifier::Git(git) => git.repo.to_string(), + } + } + + /// Gets the version (or revision) of the specifier + pub fn version(&self) -> String { + match self { + DependencySpecifier::Registry(registry) => registry.version.to_string(), + DependencySpecifier::Git(git) => git.rev.clone(), + } + } + + /// Gets the realm of the specifier + pub fn realm(&self) -> Option<&Realm> { + match self { + DependencySpecifier::Registry(registry) => registry.realm.as_ref(), + DependencySpecifier::Git(git) => git.realm.as_ref(), + } + } +} + +impl<'de> Deserialize<'de> for DependencySpecifier { + fn deserialize>(deserializer: D) -> Result { + let yaml = serde_yaml::Value::deserialize(deserializer)?; + + let result = if yaml.get("repo").is_some() { + GitDependencySpecifier::deserialize(yaml.into_deserializer()) + .map(DependencySpecifier::Git) + } else if yaml.get("name").is_some() { + RegistryDependencySpecifier::deserialize(yaml.into_deserializer()) + .map(DependencySpecifier::Registry) + } else { + Err(serde::de::Error::custom("invalid dependency")) + }; + + result.map_err(|e| serde::de::Error::custom(e.to_string())) + } +} + +// Here we don't use a custom deserializer, because this is exposed to the user only from the lock file, which mustn't be edited manually anyway +/// A reference to a package +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, Hash)] +#[serde(rename_all = "snake_case", tag = "type")] +pub enum PackageRef { + /// A reference to a package that can be downloaded from a registry + Registry(RegistryPackageRef), + /// A reference to a package that can be downloaded from a git repository + Git(GitPackageRef), +} + +/// An error that occurred while downloading a package +#[derive(Debug, Error)] +pub enum DownloadError { + /// An error that occurred while downloading a package from a registry + #[error("error downloading package {1} from registry")] + Registry(#[source] registry::RegistryDownloadError, Box), + + /// An error that occurred while downloading a package from a git repository + #[error("error downloading package {1} from git repository")] + Git(#[source] git::GitDownloadError, Box), +} + +impl PackageRef { + /// Gets the name of the package + pub fn name(&self) -> &PackageName { + match self { + PackageRef::Registry(registry) => ®istry.name, + PackageRef::Git(git) => &git.name, + } + } + + /// Gets the version of the package + pub fn version(&self) -> &Version { + match self { + PackageRef::Registry(registry) => ®istry.version, + PackageRef::Git(git) => &git.version, + } + } + + /// Downloads the package to the specified destination + pub fn download, I: Index>( + &self, + project: &Project, + dest: P, + ) -> Result<(), DownloadError> { + match self { + PackageRef::Registry(registry) => registry + .download(project, dest) + .map_err(|e| DownloadError::Registry(e, Box::new(self.clone()))), + PackageRef::Git(git) => git + .download(project, dest) + .map_err(|e| DownloadError::Git(e, Box::new(self.clone()))), + } + } +} + +impl Project { + /// Downloads the project's dependencies + pub fn download( + &self, + map: &ResolvedVersionsMap, + ) -> Result, InstallProjectError> { + let (job, tx) = MultithreadedJob::new(); + + for (name, versions) in map.clone() { + for (version, resolved_package) in versions { + let (_, source) = resolved_package.directory(self.path()); + + if source.exists() { + debug!("package {name}@{version} already downloaded, skipping..."); + continue; + } + + debug!( + "downloading package {name}@{version} to {}", + source.display() + ); + + create_dir_all(&source)?; + + let project = self.clone(); + let tx = tx.clone(); + + job.pool.execute(move || { + let result = resolved_package.pkg_ref.download(&project, source); + tx.send(result).unwrap(); + }); + } + } + + Ok(job) + } +} + +impl Display for PackageRef { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "{}@{}", self.name(), self.version()) + } +} diff --git a/src/dependencies/registry.rs b/src/dependencies/registry.rs new file mode 100644 index 0000000..7dbb323 --- /dev/null +++ b/src/dependencies/registry.rs @@ -0,0 +1,125 @@ +use std::path::Path; + +use log::{debug, error}; +use reqwest::header::{AUTHORIZATION, USER_AGENT as USER_AGENT_HEADER}; +use semver::{Version, VersionReq}; +use serde::{Deserialize, Serialize}; +use thiserror::Error; + +use crate::{ + index::Index, manifest::Realm, package_name::PackageName, project::Project, USER_AGENT, +}; + +/// A dependency of a package that can be downloaded from a registry +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, Hash)] +#[serde(deny_unknown_fields)] +pub struct RegistryDependencySpecifier { + /// The name of the package + pub name: PackageName, + /// The version requirement of the package + pub version: VersionReq, + // TODO: support per-package registries + // #[serde(skip_serializing_if = "Option::is_none")] + // pub registry: Option, + /// The realm of the package + pub realm: Option, +} + +/// A reference to a package that can be downloaded from a registry +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, Hash)] +#[serde(deny_unknown_fields)] +pub struct RegistryPackageRef { + /// The name of the package + pub name: PackageName, + /// The version of the package + pub version: Version, + // TODO: support per-package registries + // #[serde(skip_serializing_if = "Option::is_none")] + // pub index_url: Option, +} + +/// An error that occurred while downloading a package from a registry +#[derive(Debug, Error)] +pub enum RegistryDownloadError { + /// An error that occurred while interacting with reqwest + #[error("error interacting with reqwest")] + Reqwest(#[from] reqwest::Error), + + /// An error that occurred while interacting with the file system + #[error("error interacting with the file system")] + Io(#[from] std::io::Error), + + /// An error that occurred while reading the index config + #[error("error with the index config")] + IndexConfig(#[from] crate::index::ConfigError), + + /// The package was not found on the registry + #[error("package {0} not found on the registry, but found in the index")] + NotFound(PackageName), + + /// The user is unauthorized to download the package + #[error("unauthorized to download package {0}")] + Unauthorized(PackageName), + + /// An HTTP error occurred + #[error("http error {0}: the server responded with {1}")] + Http(reqwest::StatusCode, String), +} + +impl RegistryPackageRef { + /// Downloads the package to the specified destination + pub fn download, I: Index>( + &self, + project: &Project, + dest: P, + ) -> Result<(), RegistryDownloadError> { + let url = project + .index() + .config()? + .download() + .replace("{PACKAGE_AUTHOR}", self.name.scope()) + .replace("{PACKAGE_NAME}", self.name.name()) + .replace("{PACKAGE_VERSION}", &self.version.to_string()); + + debug!( + "downloading registry package {}@{} from {}", + self.name, self.version, url + ); + + let client = reqwest::blocking::Client::new(); + let response = { + let mut builder = client.get(&url).header(USER_AGENT_HEADER, USER_AGENT); + if let Some(token) = project.registry_auth_token() { + let visible_tokens = token.chars().take(8).collect::(); + let hidden_tokens = "*".repeat(token.len() - 8); + debug!("using registry token {visible_tokens}{hidden_tokens}"); + builder = builder.header(AUTHORIZATION, format!("Bearer {}", token)); + } + builder.send()? + }; + + if !response.status().is_success() { + return match response.status() { + reqwest::StatusCode::NOT_FOUND => { + Err(RegistryDownloadError::NotFound(self.name.clone())) + } + reqwest::StatusCode::UNAUTHORIZED => { + Err(RegistryDownloadError::Unauthorized(self.name.clone())) + } + _ => Err(RegistryDownloadError::Http( + response.status(), + response.text()?, + )), + }; + } + + let bytes = response.bytes()?; + + let mut decoder = flate2::read::GzDecoder::new(bytes.as_ref()); + let mut archive = tar::Archive::new(&mut decoder); + + archive.unpack(&dest)?; + + Ok(()) + } +} diff --git a/src/dependencies/resolution.rs b/src/dependencies/resolution.rs new file mode 100644 index 0000000..92ab2d4 --- /dev/null +++ b/src/dependencies/resolution.rs @@ -0,0 +1,442 @@ +use std::{ + collections::{BTreeMap, BTreeSet, VecDeque}, + fmt::Display, + path::{Path, PathBuf}, +}; + +use log::debug; +use semver::Version; +use serde::{Deserialize, Serialize}; +use thiserror::Error; + +use crate::{ + dependencies::{ + git::{GitDownloadError, GitPackageRef}, + registry::{RegistryDependencySpecifier, RegistryPackageRef}, + DependencySpecifier, PackageRef, + }, + index::{Index, IndexPackageError}, + manifest::{DependencyType, Manifest, Realm}, + package_name::PackageName, + project::{Project, ReadLockfileError}, + DEV_PACKAGES_FOLDER, INDEX_FOLDER, PACKAGES_FOLDER, SERVER_PACKAGES_FOLDER, +}; + +/// A node in the dependency tree +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, Hash)] +#[serde(deny_unknown_fields)] +pub struct ResolvedPackage { + /// The reference to the package + pub pkg_ref: PackageRef, + /// The specifier that resolved to this package + pub specifier: DependencySpecifier, + /// The dependencies of the package + #[serde(default, skip_serializing_if = "BTreeSet::is_empty")] + pub dependencies: BTreeSet<(PackageName, Version)>, + /// Whether the package is a root package (top-level dependency) + pub is_root: bool, + /// The realm of the package + pub realm: Realm, + /// The type of the dependency + pub dep_type: DependencyType, +} + +impl Display for ResolvedPackage { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "{}", self.pkg_ref) + } +} + +pub(crate) fn packages_folder(realm: &Realm) -> &str { + match realm { + Realm::Shared => PACKAGES_FOLDER, + Realm::Server => SERVER_PACKAGES_FOLDER, + Realm::Development => DEV_PACKAGES_FOLDER, + } +} + +impl ResolvedPackage { + pub(crate) fn packages_folder(&self) -> &str { + packages_folder(&self.realm) + } + + /// Returns the directory of the package in the project, and the parent of the directory + pub fn directory>(&self, project_path: P) -> (PathBuf, PathBuf) { + let name = self.pkg_ref.name().escaped(); + let container_path = project_path + .as_ref() + .join(self.packages_folder()) + .join(INDEX_FOLDER) + .join(&name) + .join(self.pkg_ref.version().to_string()); + + (container_path.clone(), container_path.join(&name)) + } +} + +/// A flat resolved map, a map of package names to versions to resolved packages +pub type ResolvedVersionsMap = BTreeMap>; + +macro_rules! find_highest { + ($iter:expr, $dep:expr) => { + $iter + .filter(|v| $dep.version.matches(v)) + .max_by(|a, b| a.cmp(&b)) + .cloned() + }; +} + +fn find_realm(a: &Realm, b: &Realm) -> Realm { + if a == b { + return *a; + } + + Realm::Shared +} + +fn add_to_map( + map: &mut ResolvedVersionsMap, + name: &PackageName, + version: &Version, + resolved_package: &ResolvedPackage, + lockfile: &ResolvedVersionsMap, + depth: usize, +) -> Result<(), ResolveError> { + debug!( + "{}resolved {resolved_package} from lockfile", + "\t".repeat(depth) + ); + + map.entry(name.clone()) + .or_default() + .insert(version.clone(), resolved_package.clone()); + + for (dep_name, dep_version) in &resolved_package.dependencies { + if map.get(dep_name).and_then(|v| v.get(dep_version)).is_none() { + let dep = lockfile.get(dep_name).and_then(|v| v.get(dep_version)); + + match dep { + Some(dep) => add_to_map(map, dep_name, dep_version, dep, lockfile, depth + 1)?, + // the lockfile is malformed + None => return Err(ResolveError::OutOfDateLockfile), + } + } + } + + Ok(()) +} + +/// An error that occurred while resolving dependencies +#[derive(Debug, Error)] +pub enum ResolveError { + /// An error that occurred while interacting with the file system + #[error("error interacting with the file system")] + Io(#[from] std::io::Error), + + /// An error that occurred because a registry dependency conflicts with a git dependency + #[error("registry dependency {0}@{1} conflicts with git dependency")] + RegistryConflict(PackageName, Version), + + /// An error that occurred because a git dependency conflicts with a registry dependency + #[error("git dependency {0}@{1} conflicts with registry dependency")] + GitConflict(PackageName, Version), + + /// An error that occurred because no satisfying version was found for a dependency + #[error("no satisfying version found for dependency {0:?}")] + NoSatisfyingVersion(RegistryDependencySpecifier), + + /// An error that occurred while downloading a package from a git repository + #[error("error downloading git package")] + GitDownload(#[from] GitDownloadError), + + /// An error that occurred because a package was not found in the index + #[error("package {0} not found in index")] + PackageNotFound(PackageName), + + /// An error that occurred while getting a package from the index + #[error("failed to get package {1} from index")] + IndexPackage(#[source] IndexPackageError, PackageName), + + /// An error that occurred while reading the lockfile + #[error("failed to read lockfile")] + LockfileRead(#[from] ReadLockfileError), + + /// An error that occurred because the lockfile is out of date + #[error("out of date lockfile")] + OutOfDateLockfile, + + /// An error that occurred because two realms are incompatible + #[error("incompatible realms for package {0} (package specified {1}, user specified {2})")] + IncompatibleRealms(PackageName, Realm, Realm), + + /// An error that occurred because a peer dependency is not installed + #[error("peer dependency {0}@{1} is not installed")] + PeerNotInstalled(PackageName, Version), +} + +impl Manifest { + /// Resolves the dependency tree for the project + pub fn dependency_tree( + &self, + project: &Project, + locked: bool, + ) -> Result { + debug!("resolving dependency tree for project {}", self.name); + // try to reuse versions (according to semver specifiers) to decrease the amount of downloads and storage + let mut resolved_versions_map: ResolvedVersionsMap = BTreeMap::new(); + + let tree = if let Some(lockfile) = project.lockfile()? { + debug!("lockfile found, resolving dependencies from it"); + let mut missing = Vec::new(); + + // resolve all root dependencies (and their dependencies) from the lockfile + for (name, versions) in &lockfile { + for (version, resolved_package) in versions { + if !resolved_package.is_root + || !self + .dependencies() + .into_iter() + .any(|(spec, _)| spec == resolved_package.specifier) + { + continue; + } + + add_to_map( + &mut resolved_versions_map, + name, + version, + resolved_package, + &lockfile, + 1, + )?; + } + } + + // resolve new, or modified, dependencies from the lockfile + 'outer: for (dep, dep_type) in self.dependencies() { + for versions in resolved_versions_map.values() { + for resolved_package in versions.values() { + if resolved_package.specifier == dep && resolved_package.is_root { + continue 'outer; + } + } + } + + if locked { + return Err(ResolveError::OutOfDateLockfile); + } + + missing.push((dep.clone(), dep_type)); + } + + debug!( + "resolved {} dependencies from lockfile. new dependencies: {}", + resolved_versions_map.len(), + missing.len() + ); + + missing + } else { + debug!("no lockfile found, resolving all dependencies"); + self.dependencies() + }; + + if tree.is_empty() { + debug!("no dependencies left to resolve, finishing..."); + return Ok(resolved_versions_map); + } + + debug!("resolving {} dependencies from index", tree.len()); + + let mut queue = VecDeque::from_iter(self.dependencies().into_iter().map(|d| (d, None))); + + while let Some(((specifier, dep_type), dependant)) = queue.pop_front() { + let (pkg_ref, default_realm, dependencies) = match &specifier { + DependencySpecifier::Registry(registry_dependency) => { + let index_entries = project + .index() + .package(®istry_dependency.name) + .map_err(|e| { + ResolveError::IndexPackage(e, registry_dependency.name.clone()) + })? + .ok_or_else(|| { + ResolveError::PackageNotFound(registry_dependency.name.clone()) + })?; + + let resolved_versions = resolved_versions_map + .entry(registry_dependency.name.clone()) + .or_default(); + + // try to find the highest already downloaded version that satisfies the requirement, otherwise find the highest satisfying version in the index + let Some(version) = + find_highest!(resolved_versions.keys(), registry_dependency).or_else( + || { + find_highest!( + index_entries.iter().map(|v| &v.version), + registry_dependency + ) + }, + ) + else { + return Err(ResolveError::NoSatisfyingVersion( + registry_dependency.clone(), + )); + }; + + let entry = index_entries + .into_iter() + .find(|e| e.version.eq(&version)) + .unwrap(); + + debug!( + "resolved registry dependency {} to {}", + registry_dependency.name, version + ); + + ( + PackageRef::Registry(RegistryPackageRef { + name: registry_dependency.name.clone(), + version: version.clone(), + }), + entry.realm, + entry.dependencies, + ) + } + DependencySpecifier::Git(git_dependency) => { + let (manifest, url, rev) = git_dependency.resolve(project)?; + + debug!( + "resolved git dependency {} to {url}#{rev}", + git_dependency.repo + ); + + ( + PackageRef::Git(GitPackageRef { + name: manifest.name.clone(), + version: manifest.version.clone(), + repo_url: url, + rev, + }), + manifest.realm, + manifest.dependencies(), + ) + } + }; + + let is_root = dependant.is_none(); + // if the dependency is a root dependency, it can be thought of as a normal dependency + let dep_type = if is_root { + DependencyType::Normal + } else { + dep_type + }; + + if let Some((dependant_name, dependant_version)) = dependant { + resolved_versions_map + .get_mut(&dependant_name) + .and_then(|v| v.get_mut(&dependant_version)) + .unwrap() + .dependencies + .insert((pkg_ref.name().clone(), pkg_ref.version().clone())); + } + + let resolved_versions = resolved_versions_map + .entry(pkg_ref.name().clone()) + .or_default(); + + if let Some(previously_resolved) = resolved_versions.get_mut(pkg_ref.version()) { + match (&pkg_ref, &previously_resolved.pkg_ref) { + (PackageRef::Registry(r), PackageRef::Git(_g)) => { + return Err(ResolveError::RegistryConflict( + r.name.clone(), + r.version.clone(), + )); + } + (PackageRef::Git(g), PackageRef::Registry(_r)) => { + return Err(ResolveError::GitConflict(g.name.clone(), g.version.clone())); + } + _ => (), + } + + if previously_resolved.dep_type == DependencyType::Peer + && dep_type == DependencyType::Normal + { + previously_resolved.dep_type = dep_type; + } + + // need not resolve the package again + continue; + } + + if specifier + .realm() + .is_some_and(|realm| realm == &Realm::Shared) + && default_realm.is_some_and(|realm| realm == Realm::Server) + { + return Err(ResolveError::IncompatibleRealms( + pkg_ref.name().clone(), + default_realm.unwrap(), + *specifier.realm().unwrap(), + )); + } + + resolved_versions.insert( + pkg_ref.version().clone(), + ResolvedPackage { + pkg_ref: pkg_ref.clone(), + specifier: specifier.clone(), + dependencies: BTreeSet::new(), + is_root, + realm: *specifier + .realm() + .copied() + .unwrap_or_default() + .or(&default_realm.unwrap_or_default()), + dep_type, + }, + ); + + for dependency in dependencies { + queue.push_back(( + dependency, + Some((pkg_ref.name().clone(), pkg_ref.version().clone())), + )); + } + } + + debug!("resolving realms and peer dependencies..."); + + for (name, versions) in resolved_versions_map.clone() { + for (version, resolved_package) in versions { + if resolved_package.dep_type == DependencyType::Peer { + return Err(ResolveError::PeerNotInstalled( + resolved_package.pkg_ref.name().clone(), + resolved_package.pkg_ref.version().clone(), + )); + } + + let mut realm = resolved_package.realm; + + for (dep_name, dep_version) in &resolved_package.dependencies { + let dep = resolved_versions_map + .get(dep_name) + .and_then(|v| v.get(dep_version)); + + if let Some(dep) = dep { + realm = find_realm(&realm, &dep.realm); + } + } + + resolved_versions_map + .get_mut(&name) + .and_then(|v| v.get_mut(&version)) + .unwrap() + .realm = realm; + } + } + + debug!("finished resolving dependency tree"); + + Ok(resolved_versions_map) + } +} diff --git a/src/index.rs b/src/index.rs new file mode 100644 index 0000000..efbf9af --- /dev/null +++ b/src/index.rs @@ -0,0 +1,558 @@ +use std::{ + collections::BTreeSet, + fmt::Debug, + fs::create_dir_all, + hash::Hash, + path::{Path, PathBuf}, + sync::Arc, +}; + +use git2::{build::RepoBuilder, Remote, Repository, Signature}; +use log::debug; +use semver::Version; +use serde::{Deserialize, Serialize}; +use thiserror::Error; + +use crate::{ + dependencies::DependencySpecifier, + manifest::{DependencyType, Manifest, Realm}, + package_name::PackageName, +}; + +/// Owners of a scope +pub type ScopeOwners = BTreeSet; + +/// A packages index +pub trait Index: Send + Sync + Debug + Clone + 'static { + /// Gets the owners of a scope + fn scope_owners(&self, scope: &str) -> Result, ScopeOwnersError>; + + /// Creates a scope + fn create_scope_for( + &mut self, + scope: &str, + owners: &ScopeOwners, + ) -> Result; + + /// Gets a package from the index + fn package(&self, name: &PackageName) -> Result, IndexPackageError>; + + /// Creates a package version + fn create_package_version( + &mut self, + manifest: &Manifest, + uploader: &u64, + ) -> Result; + + /// Gets the index's configuration + fn config(&self) -> Result; + + /// Returns a function that gets the credentials for a git repository + fn credentials_fn(&self) -> Option<&Arc>; +} + +/// A function that gets the credentials for a git repository +pub type CredentialsFn = Box< + dyn Fn() -> Box< + dyn FnMut(&str, Option<&str>, git2::CredentialType) -> Result, + > + Send + + Sync, +>; + +/// The packages index +#[derive(Clone)] +pub struct GitIndex { + path: PathBuf, + repo_url: String, + pub(crate) credentials_fn: Option>, +} + +impl Debug for GitIndex { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + f.debug_struct("GitIndex") + .field("path", &self.path) + .field("repo_url", &self.repo_url) + .finish() + } +} + +impl Hash for GitIndex { + fn hash(&self, state: &mut H) { + self.path.hash(state); + self.repo_url.hash(state); + } +} + +impl PartialEq for GitIndex { + fn eq(&self, other: &Self) -> bool { + self.path == other.path && self.repo_url == other.repo_url + } +} + +impl Eq for GitIndex {} + +/// An error that occurred while getting the index's refspec +#[derive(Debug, Error)] +pub enum GetRefSpecError { + /// An error that occurred while interacting with git + #[error("error interacting with git")] + Git(#[from] git2::Error), + + /// The refspec for the upstream branch was not found + #[error("refspec not found for upstream branch {0}")] + RefSpecNotFound(String), + + /// The refspec is not utf-8 + #[error("refspec not utf-8")] + RefSpecNotUtf8, + + /// The upstream branch was not found + #[error("upstream branch not found")] + UpstreamBranchNotFound, + + /// The upstream branch is not utf-8 + #[error("upstream branch not utf-8")] + UpstreamBranchNotUtf8, +} + +/// An error that occurred while refreshing the index +#[derive(Debug, Error)] +pub enum RefreshError { + /// An error that occurred while interacting with git + #[error("error interacting with git")] + Git(#[from] git2::Error), + + /// An error that occurred while interacting with the file system + #[error("error interacting with the file system")] + Io(#[from] std::io::Error), + + /// An error that occurred while getting the index's refspec + #[error("error getting refspec")] + GetRefSpec(#[from] GetRefSpecError), +} + +/// An error that occurred while interacting with the scope owners +#[derive(Debug, Error)] +pub enum ScopeOwnersError { + /// An error that occurred while interacting with the file system + #[error("error interacting with the file system")] + Io(#[from] std::io::Error), + + /// An error that occurred while deserializing the scope owners + #[error("error deserializing scope owners")] + ScopeOwnersDeser(#[source] serde_yaml::Error), + + /// An error that occurred while committing and pushing to the index + #[error("error committing and pushing to the index")] + CommitAndPush(#[from] CommitAndPushError), +} + +/// An error that occurred while committing and pushing to the index +#[derive(Debug, Error)] +pub enum CommitAndPushError { + /// An error that occurred while interacting with git + #[error("error interacting with git")] + Git(#[from] git2::Error), + + /// An error that occurred while interacting with the file system + #[error("error interacting with the file system")] + Io(#[from] std::io::Error), + + /// An error that occurred while getting the index's refspec + #[error("error getting refspec")] + GetRefSpec(#[from] GetRefSpecError), +} + +/// An error that occurred while getting a package from the index +#[derive(Debug, Error)] +pub enum IndexPackageError { + /// An error that occurred while interacting with the file system + #[error("error interacting with the file system")] + Io(#[from] std::io::Error), + + /// An error that occurred while deserializing the index file + #[error("error deserializing index file")] + FileDeser(#[source] serde_yaml::Error), +} + +/// An error that occurred while creating a package version +#[derive(Debug, Error)] +pub enum CreatePackageVersionError { + /// An error that occurred while interacting with the file system + #[error("error interacting with the file system")] + Io(#[from] std::io::Error), + + /// An error that occurred while getting a package from the index + #[error("error getting a package from the index")] + IndexPackage(#[from] IndexPackageError), + + /// An error that occurred while serializing the index file + #[error("error serializing index file")] + FileSer(#[source] serde_yaml::Error), + + /// An error that occurred while committing and pushing to the index + #[error("error committing and pushing to the index")] + CommitAndPush(#[from] CommitAndPushError), + + /// An error that occurred while interacting with the scope owners + #[error("error interacting with the scope owners")] + ScopeOwners(#[from] ScopeOwnersError), + + /// The scope is missing ownership + #[error("missing scope ownership")] + MissingScopeOwnership, +} + +/// An error that occurred while getting the index's configuration +#[derive(Debug, Error)] +pub enum ConfigError { + /// An error that occurred while interacting with the file system + #[error("error interacting with the file system")] + Io(#[from] std::io::Error), + + /// An error that occurred while deserializing the index config + #[error("error deserializing index config")] + ConfigDeser(#[source] serde_yaml::Error), + + /// The index does not have a config file + #[error("index does not have a config file - this is an issue with the index, please contact the maintainer of the index")] + MissingConfig, +} + +fn get_refspec( + repo: &Repository, + remote: &mut Remote, +) -> Result<(String, String), GetRefSpecError> { + let upstream_branch_buf = repo.branch_upstream_name( + repo.head()? + .name() + .ok_or(GetRefSpecError::UpstreamBranchNotFound)?, + )?; + let upstream_branch = upstream_branch_buf + .as_str() + .ok_or(GetRefSpecError::UpstreamBranchNotUtf8)?; + + let refspec_buf = remote + .refspecs() + .find(|r| r.direction() == git2::Direction::Fetch && r.dst_matches(upstream_branch)) + .ok_or(GetRefSpecError::RefSpecNotFound( + upstream_branch.to_string(), + ))? + .rtransform(upstream_branch)?; + let refspec = refspec_buf + .as_str() + .ok_or(GetRefSpecError::RefSpecNotUtf8)?; + + Ok((refspec.to_string(), upstream_branch.to_string())) +} + +pub(crate) fn remote_callbacks(index: &I) -> git2::RemoteCallbacks { + let mut remote_callbacks = git2::RemoteCallbacks::new(); + + if let Some(credentials) = &index.credentials_fn() { + let credentials = std::sync::Arc::clone(credentials); + + remote_callbacks.credentials(move |a, b, c| credentials()(a, b, c)); + } + + remote_callbacks +} + +impl GitIndex { + /// Creates a new git index. The `refresh` method must be called before using the index, preferably immediately after creating it. + pub fn new>( + path: P, + repo_url: &str, + credentials: Option, + ) -> Self { + Self { + path: path.as_ref().to_path_buf(), + repo_url: repo_url.to_string(), + credentials_fn: credentials.map(Arc::new), + } + } + + /// Gets the path of the index + pub fn path(&self) -> &Path { + &self.path + } + + /// Gets the URL of the index's repository + pub fn repo_url(&self) -> &str { + &self.repo_url + } + + /// Refreshes the index + pub fn refresh(&self) -> Result<(), RefreshError> { + let repo = if self.path.exists() { + Repository::open(&self.path).ok() + } else { + None + }; + + if let Some(repo) = repo { + let mut remote = repo.find_remote("origin")?; + let (refspec, upstream_branch) = get_refspec(&repo, &mut remote)?; + + remote.fetch( + &[&refspec], + Some(git2::FetchOptions::new().remote_callbacks(remote_callbacks(self))), + None, + )?; + + let commit = repo.find_reference(&upstream_branch)?.peel_to_commit()?; + + debug!( + "refreshing index, fetching {refspec}#{} from origin", + commit.id().to_string() + ); + + repo.reset(&commit.into_object(), git2::ResetType::Hard, None)?; + + Ok(()) + } else { + debug!( + "refreshing index - first time, cloning {} into {}", + self.repo_url, + self.path.display() + ); + create_dir_all(&self.path)?; + + let mut fetch_options = git2::FetchOptions::new(); + fetch_options.remote_callbacks(remote_callbacks(self)); + + RepoBuilder::new() + .fetch_options(fetch_options) + .clone(&self.repo_url, &self.path)?; + + Ok(()) + } + } + + /// Commits and pushes to the index + pub fn commit_and_push( + &self, + message: &str, + signature: &Signature, + ) -> Result<(), CommitAndPushError> { + let repo = Repository::open(&self.path)?; + + let mut index = repo.index()?; + index.add_all(["*"].iter(), git2::IndexAddOption::DEFAULT, None)?; + index.write()?; + + let oid = index.write_tree()?; + let tree = repo.find_tree(oid)?; + + let parent_commit = repo.head()?.peel_to_commit()?; + + repo.commit( + Some("HEAD"), + signature, + signature, + message, + &tree, + &[&parent_commit], + )?; + + let mut remote = repo.find_remote("origin")?; + + let (refspec, _) = get_refspec(&repo, &mut remote)?; + + remote.push( + &[&refspec], + Some(git2::PushOptions::new().remote_callbacks(remote_callbacks(self))), + )?; + + Ok(()) + } +} + +impl Index for GitIndex { + fn scope_owners(&self, scope: &str) -> Result, ScopeOwnersError> { + let path = self.path.join(scope).join("owners.yaml"); + + if !path.exists() { + return Ok(None); + } + + let contents = std::fs::read(&path)?; + let owners: ScopeOwners = + serde_yaml::from_slice(&contents).map_err(ScopeOwnersError::ScopeOwnersDeser)?; + + Ok(Some(owners)) + } + + fn create_scope_for( + &mut self, + scope: &str, + owners: &ScopeOwners, + ) -> Result { + let path = self.path.join(scope); + + if path.exists() { + return Ok(false); + } + + create_dir_all(&path)?; + + serde_yaml::to_writer(std::fs::File::create(path.join("owners.yaml"))?, owners) + .map_err(ScopeOwnersError::ScopeOwnersDeser)?; + + Ok(true) + } + + fn package(&self, name: &PackageName) -> Result, IndexPackageError> { + let path = self.path.join(name.scope()).join(name.name()); + + if !path.exists() { + return Ok(None); + } + + let contents = std::fs::read(&path)?; + let file: IndexFile = + serde_yaml::from_slice(&contents).map_err(IndexPackageError::FileDeser)?; + + Ok(Some(file)) + } + + fn create_package_version( + &mut self, + manifest: &Manifest, + uploader: &u64, + ) -> Result { + let scope = manifest.name.scope(); + + if let Some(owners) = self.scope_owners(scope)? { + if !owners.contains(uploader) { + return Err(CreatePackageVersionError::MissingScopeOwnership); + } + } else if !self.create_scope_for(scope, &BTreeSet::from([*uploader]))? { + return Err(CreatePackageVersionError::MissingScopeOwnership); + } + + let path = self.path.join(scope); + + let mut file = if let Some(file) = self.package(&manifest.name)? { + if file.iter().any(|e| e.version == manifest.version) { + return Ok(false); + } + file + } else { + vec![] + }; + + file.push(manifest.clone().into()); + + serde_yaml::to_writer( + std::fs::File::create(path.join(manifest.name.name()))?, + &file, + ) + .map_err(CreatePackageVersionError::FileSer)?; + + Ok(true) + } + + fn config(&self) -> Result { + let path = self.path.join("config.yaml"); + + if !path.exists() { + return Err(ConfigError::MissingConfig); + } + + let contents = std::fs::read(&path)?; + let config: IndexConfig = + serde_yaml::from_slice(&contents).map_err(ConfigError::ConfigDeser)?; + + Ok(config) + } + + fn credentials_fn(&self) -> Option<&Arc> { + self.credentials_fn.as_ref() + } +} + +/// The configuration of the index +#[derive(Serialize, Deserialize, Debug, Clone)] +#[serde(deny_unknown_fields)] +pub struct IndexConfig { + /// The URL of the index's API + pub api: String, + /// The URL of the index's download API, defaults to `{API_URL}/v0/packages/{PACKAGE_AUTHOR}/{PACKAGE_NAME}/{PACKAGE_VERSION}`. + /// Has the following variables: + /// - `{API_URL}`: The URL of the index's API + /// - `{PACKAGE_AUTHOR}`: The author of the package + /// - `{PACKAGE_NAME}`: The name of the package + /// - `{PACKAGE_VERSION}`: The version of the package + pub download: Option, + /// Whether to allow git dependencies + #[serde(default)] + pub git_allowed: bool, + /// Whether to allow custom registries + #[serde(default)] + pub custom_registry_allowed: bool, + /// The OAuth client ID for GitHub OAuth + pub github_oauth_client_id: String, +} + +impl IndexConfig { + /// Gets the URL of the index's API + pub fn api(&self) -> &str { + self.api.strip_suffix('/').unwrap_or(&self.api) + } + + /// Gets the URL of the index's download API + pub fn download(&self) -> String { + self.download + .as_ref() + .unwrap_or( + &"{API_URL}/v0/packages/{PACKAGE_AUTHOR}/{PACKAGE_NAME}/{PACKAGE_VERSION}" + .to_string(), + ) + .replace("{API_URL}", self.api()) + } +} + +/// An entry in the index file +#[derive(Serialize, Deserialize, Debug, Clone)] +#[serde(deny_unknown_fields)] +pub struct IndexFileEntry { + /// The version of the package + pub version: Version, + /// The realm of the package + pub realm: Option, + + /// A description of the package + #[serde(default, skip_serializing_if = "Option::is_none")] + pub description: Option, + /// The license of the package + #[serde(default, skip_serializing_if = "Option::is_none")] + pub license: Option, + /// The authors of the package + #[serde(default, skip_serializing_if = "Option::is_none")] + pub authors: Option>, + + /// The dependencies of the package + #[serde(default, skip_serializing_if = "Vec::is_empty")] + pub dependencies: Vec<(DependencySpecifier, DependencyType)>, +} + +impl From for IndexFileEntry { + fn from(manifest: Manifest) -> IndexFileEntry { + let dependencies = manifest.dependencies(); + + IndexFileEntry { + version: manifest.version, + realm: manifest.realm, + + description: manifest.description, + license: manifest.license, + authors: manifest.authors, + + dependencies, + } + } +} + +/// An index file +pub type IndexFile = Vec; diff --git a/src/lib.rs b/src/lib.rs new file mode 100644 index 0000000..242ac6a --- /dev/null +++ b/src/lib.rs @@ -0,0 +1,48 @@ +#![deny(missing_docs)] +//! pesde is a package manager for Roblox that is designed to be feature-rich and easy to use. +//! Currently, pesde is in a very early stage of development, but already supports the following features: +//! - Managing dependencies +//! - Re-exporting types +//! - `bin` exports (ran with Lune) +//! - Patching packages + +/// Resolving, downloading and managing dependencies +pub mod dependencies; +/// Managing the pesde index +pub mod index; +/// Creating linking files ('re-export' modules) +pub mod linking_file; +/// Managing the pesde manifest +pub mod manifest; +/// Multi-threading utilities +pub mod multithread; +/// Creating, parsing, and validating package names +pub mod package_name; +/// Managing patches +pub mod patches; +/// Managing pesde projects +pub mod project; + +/// The folder that contains shared packages +pub const PACKAGES_FOLDER: &str = "packages"; +/// The folder that contains dev packages +pub const DEV_PACKAGES_FOLDER: &str = "dev_packages"; +/// The folder that contains server packages +pub const SERVER_PACKAGES_FOLDER: &str = "server_packages"; +/// The folder that contains the packages index (where every package is stored after being downloaded) +pub const INDEX_FOLDER: &str = "pesde_index"; +/// The name of the manifest file +pub const MANIFEST_FILE_NAME: &str = "pesde.yaml"; +/// The name of the lockfile +pub const LOCKFILE_FILE_NAME: &str = "pesde-lock.yaml"; +/// The name of the patches folder +pub const PATCHES_FOLDER: &str = "patches"; +/// Files to be ignored when publishing +pub const IGNORED_FOLDERS: &[&str] = &[ + PACKAGES_FOLDER, + DEV_PACKAGES_FOLDER, + SERVER_PACKAGES_FOLDER, + ".git", +]; + +const USER_AGENT: &str = concat!(env!("CARGO_PKG_NAME"), "/", env!("CARGO_PKG_VERSION")); diff --git a/src/linking_file.rs b/src/linking_file.rs new file mode 100644 index 0000000..937f376 --- /dev/null +++ b/src/linking_file.rs @@ -0,0 +1,284 @@ +use std::{ + fs::{read, write}, + iter, + path::{Component, Path, PathBuf}, + str::from_utf8, +}; + +use full_moon::{ + ast::types::ExportedTypeDeclaration, + parse, + visitors::{Visit, Visitor}, +}; +use log::debug; +use semver::Version; +use thiserror::Error; + +use crate::{ + dependencies::resolution::{packages_folder, ResolvedPackage, ResolvedVersionsMap}, + index::Index, + manifest::{Manifest, ManifestReadError, PathStyle, Realm}, + package_name::PackageName, + project::Project, +}; + +struct TypeVisitor { + pub(crate) types: Vec, +} + +impl Visitor for TypeVisitor { + fn visit_exported_type_declaration(&mut self, node: &ExportedTypeDeclaration) { + let name = node.type_declaration().type_name().to_string(); + + let (declaration_generics, generics) = + if let Some(declaration) = node.type_declaration().generics() { + let mut declaration_generics = vec![]; + let mut generics = vec![]; + + for generic in declaration.generics().iter() { + declaration_generics.push(generic.to_string()); + + if generic.default_type().is_some() { + generics.push(generic.parameter().to_string()) + } else { + generics.push(generic.to_string()) + } + } + + ( + format!("<{}>", declaration_generics.join(", ")), + format!("<{}>", generics.join(", ")), + ) + } else { + ("".to_string(), "".to_string()) + }; + + self.types.push(format!( + "export type {name}{declaration_generics} = module.{name}{generics}\n" + )); + } +} + +/// Generates the contents of a linking file, given the require path, and the contents of the target file +/// The contents will be scanned for type exports, and the linking file will be generated accordingly +pub fn linking_file(content: &str, path: &str) -> Result { + let mut linker = format!("local module = require({path})\n"); + let mut visitor = TypeVisitor { types: vec![] }; + + parse(content)?.nodes().visit(&mut visitor); + + for ty in visitor.types { + linker.push_str(&ty); + } + + linker.push_str("return module"); + + Ok(linker) +} + +#[derive(Debug, Error)] +/// An error that occurred while linking dependencies +pub enum LinkingError { + #[error("error interacting with the file system")] + /// An error that occurred while interacting with the file system + Io(#[from] std::io::Error), + + #[error("failed getting file name from {0}")] + /// An error that occurred while getting a file name + FileNameFail(PathBuf), + + #[error("failed converting file name to string")] + /// An error that occurred while converting a file name to a string + FileNameToStringFail, + + #[error("failed getting relative path from {0} to {1}")] + /// An error that occurred while getting a relative path + RelativePathFail(PathBuf, PathBuf), + + #[error("failed getting path parent of {0}")] + /// An error that occurred while getting a path parent + ParentFail(PathBuf), + + #[error("failed to convert path component to string")] + /// An error that occurred while converting a path component to a string + ComponentToStringFail, + + #[error("failed to get path string")] + /// An error that occurred while getting a path string + PathToStringFail, + + #[error("error encoding utf-8 string")] + /// An error that occurred while converting a byte slice to a string + Utf8(#[from] std::str::Utf8Error), + + #[error("error reading manifest")] + /// An error that occurred while reading the manifest of a package + ManifestRead(#[from] ManifestReadError), + + #[error("missing realm {0} in-game path")] + /// An error that occurred while getting the in-game path for a realm + MissingRealmInGamePath(Realm), + + #[error("library source is not valid Luau")] + /// An error that occurred because the library source is not valid Luau + InvalidLuau(#[from] full_moon::Error), +} + +pub(crate) fn link, Q: AsRef, I: Index>( + project: &Project, + resolved_pkg: &ResolvedPackage, + destination_dir: P, + parent_dependency_packages_dir: Q, +) -> Result<(), LinkingError> { + let (_, source_dir) = resolved_pkg.directory(project.path()); + let file = Manifest::from_path(&source_dir)?; + + let Some(lib_export) = file.exports.lib else { + return Ok(()); + }; + + let lib_export = lib_export.to_path(&source_dir); + + let path_style = &project.manifest().path_style; + let PathStyle::Roblox { place } = &path_style; + + debug!("linking {resolved_pkg} using `{}` path style", path_style); + + let name = resolved_pkg.pkg_ref.name().name(); + + let destination_dir = if resolved_pkg.is_root { + project.path().join(packages_folder( + &resolved_pkg.specifier.realm().cloned().unwrap_or_default(), + )) + } else { + destination_dir.as_ref().to_path_buf() + }; + + let destination_file = destination_dir.join(format!("{name}.lua")); + + let realm_folder = project.path().join(resolved_pkg.packages_folder()); + let in_different_folders = realm_folder != parent_dependency_packages_dir.as_ref(); + + let mut path = if in_different_folders { + pathdiff::diff_paths(&source_dir, &realm_folder) + .ok_or_else(|| LinkingError::RelativePathFail(source_dir.clone(), realm_folder))? + } else { + pathdiff::diff_paths(&source_dir, &destination_dir).ok_or_else(|| { + LinkingError::RelativePathFail(source_dir.clone(), destination_dir.to_path_buf()) + })? + }; + path.set_extension(""); + + let beginning = if in_different_folders { + place + .get(&resolved_pkg.realm) + .ok_or_else(|| LinkingError::MissingRealmInGamePath(resolved_pkg.realm))? + .clone() + } else if name == "init" { + "script".to_string() + } else { + "script.Parent".to_string() + }; + + let path = iter::once(Ok(beginning)) + .chain(path.components().map(|component| { + Ok(match component { + Component::ParentDir => ".Parent".to_string(), + Component::Normal(part) => format!( + "[{:?}]", + part.to_str().ok_or(LinkingError::ComponentToStringFail)? + ), + _ => unreachable!("invalid path component"), + }) + })) + .collect::>()?; + + debug!( + "writing linking file for {} with import `{path}` to {}", + source_dir.display(), + destination_file.display() + ); + + let raw_file_contents = read(lib_export)?; + let file_contents = from_utf8(&raw_file_contents)?; + + let linking_file_contents = linking_file(file_contents, &path)?; + + write(&destination_file, linking_file_contents)?; + + Ok(()) +} + +#[derive(Debug, Error)] +#[error("error linking {1}@{2} to {3}@{4}")] +/// An error that occurred while linking the dependencies +pub struct LinkingDependenciesError( + #[source] LinkingError, + PackageName, + Version, + PackageName, + Version, +); + +impl Project { + /// Links the dependencies of the project + pub fn link_dependencies( + &self, + map: &ResolvedVersionsMap, + ) -> Result<(), LinkingDependenciesError> { + for (name, versions) in map { + for (version, resolved_pkg) in versions { + let (container_dir, _) = resolved_pkg.directory(self.path()); + + debug!( + "linking package {name}@{version}'s dependencies to directory {}", + container_dir.display() + ); + + for (dep_name, dep_version) in &resolved_pkg.dependencies { + let dep = map + .get(dep_name) + .and_then(|versions| versions.get(dep_version)) + .unwrap(); + + link( + self, + dep, + &container_dir, + &self.path().join(resolved_pkg.packages_folder()), + ) + .map_err(|e| { + LinkingDependenciesError( + e, + dep_name.clone(), + dep_version.clone(), + name.clone(), + version.clone(), + ) + })?; + } + + if resolved_pkg.is_root { + let linking_dir = &self.path().join(resolved_pkg.packages_folder()); + + debug!( + "linking root package {name}@{version} to directory {}", + linking_dir.display() + ); + + link(self, resolved_pkg, linking_dir, linking_dir).map_err(|e| { + LinkingDependenciesError( + e, + name.clone(), + version.clone(), + name.clone(), + version.clone(), + ) + })?; + } + } + } + + Ok(()) + } +} diff --git a/src/main.rs b/src/main.rs new file mode 100644 index 0000000..6ddf591 --- /dev/null +++ b/src/main.rs @@ -0,0 +1,217 @@ +use std::{ + fs::{create_dir_all, read}, + hash::{DefaultHasher, Hash, Hasher}, + path::PathBuf, +}; + +use auth_git2::GitAuthenticator; +use clap::{Parser, Subcommand}; +use directories::ProjectDirs; +use indicatif::MultiProgress; +use indicatif_log_bridge::LogWrapper; +use keyring::Entry; +use pretty_env_logger::env_logger::Env; +use reqwest::header::{ACCEPT, AUTHORIZATION}; +use serde::{Deserialize, Serialize}; + +use cli::{ + auth::{auth_command, AuthCommand}, + config::{config_command, ConfigCommand}, + root::root_command, +}; +use pesde::index::GitIndex; + +mod cli; + +#[derive(Subcommand)] +pub enum Command { + /// Installs the dependencies of the project + Install { + #[clap(long, short)] + locked: bool, + }, + + /// Runs the `bin` export of the specified package + Run { + #[clap(value_name = "PACKAGE")] + package: String, + + #[clap(last = true)] + args: Vec, + }, + + /// Searches for a package on the registry + Search { + #[clap(value_name = "QUERY")] + query: Option, + }, + + /// Publishes the project to the registry + Publish, + + /// Begins a new patch + Patch { package: String }, + + /// Commits (finished) the patch + PatchCommit { + #[clap(value_name = "DIRECTORY")] + dir: PathBuf, + }, + + /// Auth-related commands + Auth { + #[clap(subcommand)] + command: AuthCommand, + }, + + /// Config-related commands + Config { + #[clap(subcommand)] + command: ConfigCommand, + }, +} + +#[derive(Parser)] +struct Cli { + #[clap(subcommand)] + command: Command, + + #[arg(short, long, value_name = "DIRECTORY")] + directory: Option, +} + +#[derive(Serialize, Deserialize, Clone)] +struct CliConfig { + index_repo_url: String, + cache_dir: Option, +} + +impl CliConfig { + fn cache_dir(&self, directories: &ProjectDirs) -> PathBuf { + self.cache_dir + .clone() + .unwrap_or_else(|| directories.cache_dir().to_path_buf()) + } +} + +struct CliParams { + index: GitIndex, + api_token_entry: Entry, + reqwest_client: reqwest::blocking::Client, + cli_config: CliConfig, + cwd: PathBuf, + multi: MultiProgress, + directories: ProjectDirs, +} + +impl CliConfig { + fn write(&self, directories: &ProjectDirs) -> anyhow::Result<()> { + let cli_config_path = directories.config_dir().join("config.yaml"); + serde_yaml::to_writer( + &mut std::fs::File::create(cli_config_path.as_path())?, + &self, + )?; + + Ok(()) + } +} + +#[macro_export] +macro_rules! send_request { + ($req:expr) => {{ + let res = $req.send()?; + + match res.error_for_status_ref() { + Ok(_) => res, + Err(e) => { + panic!("request failed: {e}\nbody: {}", res.text()?); + } + } + }}; +} + +fn main() -> anyhow::Result<()> { + let logger = pretty_env_logger::formatted_builder() + .parse_env(Env::default().default_filter_or("info")) + .build(); + let multi = MultiProgress::new(); + + LogWrapper::new(multi.clone(), logger).try_init().unwrap(); + + let cli = Cli::parse(); + + let directories = ProjectDirs::from("com", env!("CARGO_BIN_NAME"), env!("CARGO_BIN_NAME")) + .expect("couldn't get home directory"); + + let cli_config_path = directories.config_dir().join("config.yaml"); + let cli_config = if cli_config_path.exists() { + serde_yaml::from_slice(&read(cli_config_path.as_path())?)? + } else { + let config = CliConfig { + index_repo_url: "https://github.com/daimond113/pesde-index".to_string(), + cache_dir: None, + }; + create_dir_all(directories.config_dir())?; + config.write(&directories)?; + config + }; + + let cwd_buf = cli + .directory + .or(std::env::current_dir().ok()) + .ok_or(anyhow::anyhow!("couldn't get current directory"))?; + + let api_token_entry = Entry::new(env!("CARGO_BIN_NAME"), "api_token")?; + + let mut hasher = DefaultHasher::new(); + cli_config.index_repo_url.hash(&mut hasher); + let hash = hasher.finish().to_string(); + + let index = GitIndex::new( + cli_config.cache_dir(&directories).join("index").join(hash), + &cli_config.index_repo_url, + Some(Box::new(|| { + Box::new(|a, b, c| { + let git_authenticator = GitAuthenticator::new(); + let config = git2::Config::open_default().unwrap(); + let mut cred = git_authenticator.credentials(&config); + + cred(a, b, c) + }) + })), + ); + index.refresh()?; + + let mut header_map = reqwest::header::HeaderMap::new(); + header_map.insert(ACCEPT, "application/json".parse()?); + header_map.insert( + AUTHORIZATION, + format!("Bearer {}", api_token_entry.get_password()?).parse()?, + ); + header_map.insert("X-GitHub-Api-Version", "2022-11-28".parse()?); + + let reqwest_client = reqwest::blocking::Client::builder() + .user_agent(concat!( + env!("CARGO_PKG_NAME"), + "/", + env!("CARGO_PKG_VERSION") + )) + .default_headers(header_map) + .build()?; + + let params = CliParams { + index, + api_token_entry, + reqwest_client, + cli_config, + cwd: cwd_buf, + multi, + directories, + }; + + match cli.command { + Command::Auth { command } => auth_command(command, params), + Command::Config { command } => config_command(command, params), + cmd => root_command(cmd, params), + } +} diff --git a/src/manifest.rs b/src/manifest.rs new file mode 100644 index 0000000..50d1b76 --- /dev/null +++ b/src/manifest.rs @@ -0,0 +1,180 @@ +use std::{collections::BTreeMap, fmt::Display, fs::read}; + +use relative_path::RelativePathBuf; +use semver::Version; +use serde::{Deserialize, Serialize}; +use thiserror::Error; + +use crate::{dependencies::DependencySpecifier, package_name::PackageName, MANIFEST_FILE_NAME}; + +/// The files exported by the package +#[derive(Serialize, Deserialize, Debug, Clone, Default)] +#[serde(deny_unknown_fields)] +pub struct Exports { + /// Points to the file which exports the package. As of currently this is only used for re-exporting types. + /// Libraries must have a structure in Roblox where the main file becomes the folder, for example: + /// A package called pesde/lib has a file called src/main.lua. + /// Pesde puts this package in a folder called pesde_lib. + /// The package has to have set up configuration for file-syncing tools such as Rojo so that src/main.lua becomes the pesde_lib and turns it into a ModuleScript + #[serde(default, skip_serializing_if = "Option::is_none")] + pub lib: Option, + + /// Points to the file that will be executed with Lune + #[serde(default, skip_serializing_if = "Option::is_none")] + pub bin: Option, +} + +/// The path style used by the package +#[derive(Serialize, Deserialize, Debug, Clone)] +#[serde(rename_all = "snake_case", deny_unknown_fields)] +pub enum PathStyle { + /// The path style used by Roblox (e.g. `script.Parent` or `script.Parent.Parent`) + Roblox { + /// A map of realm to in-game package folder location (used for linking between packages in different realms) + #[serde(default)] + place: BTreeMap, + }, +} + +impl Default for PathStyle { + fn default() -> Self { + PathStyle::Roblox { + place: BTreeMap::new(), + } + } +} + +impl Display for PathStyle { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + PathStyle::Roblox { .. } => write!(f, "roblox"), + } + } +} + +/// The realm of the package +#[derive( + Serialize, Deserialize, Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord, Copy, Default, +)] +#[serde(rename_all = "snake_case", deny_unknown_fields)] +pub enum Realm { + /// The package is shared (usually ReplicatedStorage) + #[default] + Shared, + /// The package is server only (usually ServerScriptService/ServerStorage) + Server, + /// The package is development only + Development, +} + +impl Realm { + /// Returns the most restrictive realm + pub fn or<'a>(&'a self, other: &'a Self) -> &'a Self { + match self { + Realm::Shared => other, + _ => self, + } + } +} + +impl Display for Realm { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + Realm::Shared => write!(f, "shared"), + Realm::Server => write!(f, "server"), + Realm::Development => write!(f, "development"), + } + } +} + +/// The manifest of a package +#[derive(Serialize, Deserialize, Debug, Clone)] +// #[serde(deny_unknown_fields)] +pub struct Manifest { + /// The name of the package + pub name: PackageName, + /// The version of the package. Must be [semver](https://semver.org) compatible. The registry will not accept non-semver versions and the CLI will not handle such packages + pub version: Version, + /// The files exported by the package + #[serde(default)] + pub exports: Exports, + /// The path style to use for linking modules + #[serde(default)] + pub path_style: PathStyle, + /// Whether the package is private (it should not be published) + #[serde(default)] + pub private: bool, + /// The realm of the package + pub realm: Option, + + /// The dependencies of the package + #[serde(default, skip_serializing_if = "Vec::is_empty")] + pub dependencies: Vec, + /// The peer dependencies of the package + #[serde(default, skip_serializing_if = "Vec::is_empty")] + pub peer_dependencies: Vec, + + /// A short description of the package + #[serde(default, skip_serializing_if = "Option::is_none")] + pub description: Option, + /// The license of the package + #[serde(default, skip_serializing_if = "Option::is_none")] + pub license: Option, + /// The authors of the package + #[serde(default, skip_serializing_if = "Option::is_none")] + pub authors: Option>, +} + +/// An error that occurred while reading the manifest +#[derive(Debug, Error)] +pub enum ManifestReadError { + /// An error that occurred while interacting with the file system + #[error("error interacting with the file system")] + Io(#[from] std::io::Error), + + /// An error that occurred while deserializing the manifest + #[error("error deserializing manifest")] + ManifestDeser(#[source] serde_yaml::Error), +} + +/// The type of dependency +#[derive(Serialize, Deserialize, Debug, Clone, Copy, PartialEq, Eq, Hash, Default)] +#[serde(rename_all = "snake_case")] +pub enum DependencyType { + /// A normal dependency + #[default] + Normal, + /// A peer dependency + Peer, +} + +impl Manifest { + /// Reads a manifest from a path (if the path is a directory, it will look for the manifest file inside it, otherwise it will read the file directly) + pub fn from_path>(path: P) -> Result { + let path = path.as_ref(); + let path = if path.file_name() == Some(MANIFEST_FILE_NAME.as_ref()) { + path.to_path_buf() + } else { + path.join(MANIFEST_FILE_NAME) + }; + + let raw_contents = read(path)?; + let manifest = + serde_yaml::from_slice(&raw_contents).map_err(ManifestReadError::ManifestDeser)?; + + Ok(manifest) + } + + /// Returns all dependencies + pub fn dependencies(&self) -> Vec<(DependencySpecifier, DependencyType)> { + self.dependencies + .iter() + .map(|dep| (dep.clone(), DependencyType::Normal)) + .chain( + self.peer_dependencies + .iter() + .map(|dep| (dep.clone(), DependencyType::Peer)), + ) + .collect() + } +} diff --git a/src/multithread.rs b/src/multithread.rs new file mode 100644 index 0000000..d1f7e1e --- /dev/null +++ b/src/multithread.rs @@ -0,0 +1,33 @@ +use std::sync::mpsc::Receiver; +use threadpool::ThreadPool; + +/// A multithreaded job +pub struct MultithreadedJob { + pub(crate) progress: Receiver>, + pub(crate) pool: ThreadPool, +} + +impl MultithreadedJob { + pub(crate) fn new() -> (Self, std::sync::mpsc::Sender>) { + let (tx, rx) = std::sync::mpsc::channel(); + let pool = ThreadPool::new(6); + + (Self { progress: rx, pool }, tx) + } + + /// Returns the progress of the job + pub fn progress(&self) -> &Receiver> { + &self.progress + } + + /// Waits for the job to finish + pub fn wait(self) -> Result<(), E> { + self.pool.join(); + + for result in self.progress { + result?; + } + + Ok(()) + } +} diff --git a/src/package_name.rs b/src/package_name.rs new file mode 100644 index 0000000..57bd899 --- /dev/null +++ b/src/package_name.rs @@ -0,0 +1,151 @@ +use std::{fmt::Display, str::FromStr}; + +use serde::{de::Visitor, Deserialize, Serialize}; +use thiserror::Error; + +/// A package name +#[derive(Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)] +pub struct PackageName(String, String); + +/// An error that occurred while validating a package name part (scope or name) +#[derive(Debug, Error)] +pub enum PackageNameValidationError { + /// The package name part is empty + #[error("package name part cannot be empty")] + EmptyPart, + /// The package name part contains invalid characters (only lowercase ASCII characters, numbers, and underscores are allowed) + #[error("package name {0} part can only contain lowercase ASCII characters, numbers, and underscores")] + InvalidPart(String), + /// The package name part is too long (it cannot be longer than 24 characters) + #[error("package name {0} part cannot be longer than 24 characters")] + PartTooLong(String), +} + +/// Validates a package name part (scope or name) +pub fn validate_part(part: &str) -> Result<(), PackageNameValidationError> { + if part.is_empty() { + return Err(PackageNameValidationError::EmptyPart); + } + + if !part + .chars() + .all(|c| c.is_ascii_lowercase() || c.is_ascii_digit() || c == '_') + { + return Err(PackageNameValidationError::InvalidPart(part.to_string())); + } + + if part.len() > 24 { + return Err(PackageNameValidationError::PartTooLong(part.to_string())); + } + + Ok(()) +} + +const SEPARATOR: char = '/'; +const ESCAPED_SEPARATOR: char = '-'; + +/// An error that occurred while parsing an escaped package name +#[derive(Debug, Error)] +pub enum EscapedPackageNameError { + /// This is not a valid escaped package name + #[error("package name is not in the format `scope{ESCAPED_SEPARATOR}name`")] + Invalid, + + /// The package name is invalid + #[error("invalid package name")] + InvalidName(#[from] PackageNameValidationError), +} + +impl PackageName { + /// Creates a new package name + pub fn new(scope: &str, name: &str) -> Result { + validate_part(scope)?; + validate_part(name)?; + + Ok(Self(scope.to_string(), name.to_string())) + } + + /// Parses an escaped package name + pub fn from_escaped(s: &str) -> Result { + let (scope, name) = s + .split_once(ESCAPED_SEPARATOR) + .ok_or(EscapedPackageNameError::Invalid)?; + Ok(Self::new(scope, name)?) + } + + /// Gets the scope of the package name + pub fn scope(&self) -> &str { + &self.0 + } + + /// Gets the name of the package name + pub fn name(&self) -> &str { + &self.1 + } + + /// Gets the escaped form (for use in file names, etc.) of the package name + pub fn escaped(&self) -> String { + format!("{}{ESCAPED_SEPARATOR}{}", self.0, self.1) + } + + /// Gets the parts of the package name + pub fn parts(&self) -> (&str, &str) { + (&self.0, &self.1) + } +} + +impl Display for PackageName { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "{}{SEPARATOR}{}", self.0, self.1) + } +} + +/// An error that occurred while parsing a package name +#[derive(Debug, Error)] +pub enum FromStrPackageNameParseError { + /// This is not a valid package name + #[error("package name is not in the format `scope{SEPARATOR}name`")] + Invalid, + /// The package name is invalid + #[error("invalid name part")] + InvalidPart(#[from] PackageNameValidationError), +} + +impl FromStr for PackageName { + type Err = FromStrPackageNameParseError; + + fn from_str(s: &str) -> Result { + let parts: Vec<&str> = s.split(SEPARATOR).collect(); + if parts.len() != 2 { + return Err(FromStrPackageNameParseError::Invalid); + } + + Ok(PackageName::new(parts[0], parts[1])?) + } +} + +impl Serialize for PackageName { + fn serialize(&self, serializer: S) -> Result { + serializer.serialize_str(&self.to_string()) + } +} + +struct PackageNameVisitor; + +impl<'de> Visitor<'de> for PackageNameVisitor { + type Value = PackageName; + + fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result { + write!(formatter, "a string in the format `scope{SEPARATOR}name`") + } + + fn visit_str(self, v: &str) -> Result { + v.parse().map_err(|e| E::custom(e)) + } +} + +impl<'de> Deserialize<'de> for PackageName { + fn deserialize>(deserializer: D) -> Result { + deserializer.deserialize_str(PackageNameVisitor) + } +} diff --git a/src/patches.rs b/src/patches.rs new file mode 100644 index 0000000..d56e60e --- /dev/null +++ b/src/patches.rs @@ -0,0 +1,210 @@ +use std::{ + fs::{read, read_dir}, + path::{Path, PathBuf}, +}; + +use git2::{ApplyLocation, Diff, DiffFormat, DiffLineType, Repository, Signature}; +use log::debug; +use semver::Version; +use thiserror::Error; + +use crate::{ + dependencies::resolution::ResolvedVersionsMap, index::Index, package_name::PackageName, + project::Project, PATCHES_FOLDER, +}; + +fn make_signature<'a>() -> Result, git2::Error> { + Signature::now( + env!("CARGO_PKG_NAME"), + concat!(env!("CARGO_PKG_NAME"), "@localhost"), + ) +} + +/// Sets up a patches repository in the specified directory +pub fn setup_patches_repo>(dir: P) -> Result { + let repo = Repository::init(&dir)?; + + { + let signature = make_signature()?; + let mut index = repo.index()?; + index.add_all(["*"].iter(), git2::IndexAddOption::DEFAULT, None)?; + index.write()?; + + let oid = index.write_tree()?; + let tree = repo.find_tree(oid)?; + + repo.commit(Some("HEAD"), &signature, &signature, "original", &tree, &[])?; + } + + Ok(repo) +} + +/// An error that occurred while creating patches +#[derive(Debug, Error)] +pub enum CreatePatchError { + /// An error that occurred while interacting with the file system + #[error("error interacting with the file system")] + Io(#[from] std::io::Error), + + /// An error that occurred while interacting with git + #[error("error interacting with git")] + Git(#[from] git2::Error), + + /// An error that occurred while getting a file name + #[error("failed to get file name from {0}")] + FileNameFail(PathBuf), + + /// An error that occurred while stripping a prefix + #[error("error stripping prefix {1} from path {2}")] + StripPrefixFail(#[source] std::path::StripPrefixError, PathBuf, PathBuf), +} + +/// Creates a patch for the package in the specified directory +pub fn create_patch>(dir: P) -> Result, CreatePatchError> { + let mut patches = vec![]; + let repo = Repository::open(dir.as_ref())?; + + let original = repo.head()?.peel_to_tree()?; + let diff = repo.diff_tree_to_workdir(Some(&original), None)?; + + diff.print(DiffFormat::Patch, |_delta, _hunk, line| { + match line.origin_value() { + DiffLineType::Context | DiffLineType::Addition | DiffLineType::Deletion => { + let origin = line.origin(); + let mut buffer = vec![0; origin.len_utf8()]; + origin.encode_utf8(&mut buffer); + patches.extend(buffer); + } + _ => {} + } + patches.extend(line.content()); + + true + })?; + + Ok(patches) +} + +/// An error that occurred while applying patches +#[derive(Debug, Error)] +pub enum ApplyPatchesError { + /// An error that occurred while interacting with the file system + #[error("error interacting with the file system")] + Io(#[from] std::io::Error), + + /// An error that occurred while interacting with git + #[error("error interacting with git")] + Git(#[from] git2::Error), + + /// An error that occurred while getting a file name + #[error("failed to get file name from {0}")] + FileNameFail(PathBuf), + + /// An error that occurred while converting a path to a string + #[error("failed to convert path to string")] + ToStringFail, + + /// An error that occurred because a patch name was malformed + #[error("malformed patch name {0}")] + MalformedPatch(String), + + /// An error that occurred while parsing a package name + #[error("failed to parse package name {0}")] + PackageNameParse(#[from] crate::package_name::EscapedPackageNameError), + + /// An error that occurred while getting a file stem + #[error("failed to get file stem")] + FileStemFail, + + /// An error that occurred while reading a file + #[error("failed to read file")] + ReadFail, + + /// An error that occurred because a package was not found in the dependencies + #[error("package {0} not found in the lockfile")] + PackageNotFound(PackageName), + + /// An error that occurred because a version was not found for a package + #[error("version {0} not found for package {1}")] + VersionNotFound(Version, PackageName), + + /// An error that occurred while parsing a version + #[error("failed to parse version")] + VersionParse(#[from] semver::Error), + + /// An error that occurred while stripping a prefix + #[error("strip prefix error")] + StripPrefixFail(#[from] std::path::StripPrefixError), +} + +impl Project { + /// Applies patches for the project + pub fn apply_patches(&self, map: &ResolvedVersionsMap) -> Result<(), ApplyPatchesError> { + let patches_dir = self.path().join(PATCHES_FOLDER); + if !patches_dir.exists() { + return Ok(()); + } + + for file in read_dir(&patches_dir)? { + let file = file?; + if !file.file_type()?.is_file() { + continue; + } + + let path = file.path(); + + let dir_name = path + .file_name() + .ok_or_else(|| ApplyPatchesError::FileNameFail(path.clone()))?; + let dir_name = dir_name.to_str().ok_or(ApplyPatchesError::ToStringFail)?; + + let (package_name, version) = dir_name + .strip_suffix(".patch") + .unwrap_or(dir_name) + .split_once('@') + .ok_or_else(|| ApplyPatchesError::MalformedPatch(dir_name.to_string()))?; + + let package_name = PackageName::from_escaped(package_name)?; + let version = Version::parse(version)?; + + let versions = map + .get(&package_name) + .ok_or_else(|| ApplyPatchesError::PackageNotFound(package_name.clone()))?; + + let resolved_pkg = versions.get(&version).ok_or_else(|| { + ApplyPatchesError::VersionNotFound(version.clone(), package_name.clone()) + })?; + + debug!("resolved package {package_name}@{version} to {resolved_pkg}"); + + let (_, source_path) = resolved_pkg.directory(self.path()); + let diff = Diff::from_buffer(&read(&path)?)?; + + let repo = match Repository::open(&source_path) { + Ok(repo) => repo, + Err(_) => setup_patches_repo(&source_path)?, + }; + + repo.apply(&diff, ApplyLocation::Both, None)?; + + let mut index = repo.index()?; + index.add_all(["*"].iter(), git2::IndexAddOption::DEFAULT, None)?; + index.write()?; + + let signature = make_signature()?; + let tree_id = index.write_tree()?; + let tree = repo.find_tree(tree_id)?; + let parent = repo.head()?.peel_to_commit()?; + repo.commit( + Some("HEAD"), + &signature, + &signature, + "applied patches", + &tree, + &[&parent], + )?; + } + + Ok(()) + } +} diff --git a/src/project.rs b/src/project.rs new file mode 100644 index 0000000..cfdf724 --- /dev/null +++ b/src/project.rs @@ -0,0 +1,219 @@ +use std::{ + fmt::Debug, + fs::{read, File}, + path::{Path, PathBuf}, +}; +use thiserror::Error; + +use crate::dependencies::DownloadError; +use crate::index::Index; +use crate::linking_file::LinkingDependenciesError; +use crate::{ + dependencies::resolution::ResolvedVersionsMap, + manifest::{Manifest, ManifestReadError}, + LOCKFILE_FILE_NAME, +}; + +/// A pesde project +#[derive(Clone, Debug)] +pub struct Project { + path: PathBuf, + cache_path: PathBuf, + index: I, + manifest: Manifest, + registry_auth_token: Option, +} + +/// Options for installing a project +pub struct InstallOptions { + locked: bool, + auto_download: bool, + resolved_versions_map: Option, +} + +impl Default for InstallOptions { + fn default() -> Self { + Self { + locked: false, + auto_download: true, + resolved_versions_map: None, + } + } +} + +impl InstallOptions { + /// Creates a new set of install options (uses the Default implementation) + pub fn new() -> Self { + Self::default() + } + + /// Makes the installation to use the lockfile, and ensure that the lockfile is up-to-date + pub fn locked(&self, locked: bool) -> Self { + Self { + locked, + resolved_versions_map: self.resolved_versions_map.clone(), + ..*self + } + } + + /// Makes the installation to automatically download the dependencies + /// Having this set to false is only useful if you want to download the dependencies yourself. An example of this is the CLI's progress bar + pub fn auto_download(&self, auto_download: bool) -> Self { + Self { + auto_download, + resolved_versions_map: self.resolved_versions_map.clone(), + ..*self + } + } + + /// Makes the installation to use the given resolved versions map + /// Having this set to Some is only useful if you're using auto_download = false + pub fn resolved_versions_map(&self, resolved_versions_map: ResolvedVersionsMap) -> Self { + Self { + resolved_versions_map: Some(resolved_versions_map), + ..*self + } + } +} + +/// An error that occurred while reading the lockfile +#[derive(Debug, Error)] +pub enum ReadLockfileError { + /// An error that occurred while interacting with the file system + #[error("error interacting with the file system")] + Io(#[from] std::io::Error), + + /// An error that occurred while deserializing the lockfile + #[error("error deserializing lockfile")] + LockfileDeser(#[source] serde_yaml::Error), +} + +/// An error that occurred while downloading a project +#[derive(Debug, Error)] +pub enum InstallProjectError { + /// An error that occurred while resolving the dependency tree + #[error("failed to resolve dependency tree")] + ResolveTree(#[from] crate::dependencies::resolution::ResolveError), + + /// An error that occurred while downloading a package + #[error("failed to download package")] + DownloadPackage(#[from] DownloadError), + + /// An error that occurred while applying patches + #[error("error applying patches")] + ApplyPatches(#[from] crate::patches::ApplyPatchesError), + + /// An error that occurred while linking dependencies + #[error("failed to link dependencies")] + Linking(#[from] LinkingDependenciesError), + + /// An error that occurred while interacting with the file system + #[error("error interacting with the file system")] + Io(#[from] std::io::Error), + + /// An error that occurred while writing the lockfile + #[error("failed to write lockfile")] + LockfileSer(#[source] serde_yaml::Error), +} + +impl Project { + /// Creates a new project + pub fn new, Q: AsRef>( + path: P, + cache_path: Q, + index: I, + manifest: Manifest, + registry_auth_token: Option, + ) -> Self { + Self { + path: path.as_ref().to_path_buf(), + cache_path: cache_path.as_ref().to_path_buf(), + index, + manifest, + registry_auth_token, + } + } + + /// Creates a new project from a path (manifest will be read from the path) + pub fn from_path, Q: AsRef>( + path: P, + cache_path: Q, + index: I, + registry_auth_token: Option, + ) -> Result { + let manifest = Manifest::from_path(path.as_ref())?; + + Ok(Self::new( + path, + cache_path, + index, + manifest, + registry_auth_token, + )) + } + + /// Returns the index of the project + pub fn index(&self) -> &I { + &self.index + } + + /// Returns the manifest of the project + pub fn manifest(&self) -> &Manifest { + &self.manifest + } + + /// Returns the cache directory of the project + pub fn cache_dir(&self) -> &Path { + &self.cache_path + } + + /// Returns the path of the project + pub fn path(&self) -> &Path { + &self.path + } + + /// Returns the registry auth token of the project + pub fn registry_auth_token(&self) -> Option<&String> { + self.registry_auth_token.as_ref() + } + + /// Returns the lockfile of the project + pub fn lockfile(&self) -> Result, ReadLockfileError> { + let lockfile_path = self.path.join(LOCKFILE_FILE_NAME); + + Ok(if lockfile_path.exists() { + let lockfile_contents = read(&lockfile_path)?; + let lockfile: ResolvedVersionsMap = serde_yaml::from_slice(&lockfile_contents) + .map_err(ReadLockfileError::LockfileDeser)?; + + Some(lockfile) + } else { + None + }) + } + + /// Downloads the project's dependencies, applies patches, and links the dependencies + pub fn install(&self, install_options: InstallOptions) -> Result<(), InstallProjectError> { + let map = match install_options.resolved_versions_map { + Some(map) => map, + None => self + .manifest + .dependency_tree(self, install_options.locked)?, + }; + + if install_options.auto_download { + self.download(&map)?.wait()?; + } + + self.apply_patches(&map)?; + + self.link_dependencies(&map)?; + + if !install_options.locked { + serde_yaml::to_writer(File::create(self.path.join(LOCKFILE_FILE_NAME))?, &map) + .map_err(InstallProjectError::LockfileSer)?; + } + + Ok(()) + } +} diff --git a/tests/prelude.rs b/tests/prelude.rs new file mode 100644 index 0000000..4072f3b --- /dev/null +++ b/tests/prelude.rs @@ -0,0 +1,99 @@ +use std::{ + collections::{BTreeSet, HashMap}, + sync::Arc, +}; + +use pesde::{ + index::{ + ConfigError, CreatePackageVersionError, CredentialsFn, Index, IndexConfig, IndexFile, + IndexFileEntry, IndexPackageError, ScopeOwners, ScopeOwnersError, + }, + manifest::Manifest, + package_name::PackageName, +}; + +/// An in-memory implementation of the [`Index`] trait. Used for testing. +#[derive(Debug, Clone, Default)] +pub struct InMemoryIndex { + packages: HashMap, IndexFile)>, +} + +impl InMemoryIndex { + pub fn new() -> Self { + Self::default() + } + + pub fn with_scope(mut self, scope: &str, owners: BTreeSet) -> Self { + self.packages + .insert(scope.to_string(), (owners, IndexFile::default())); + self + } + + pub fn with_package(mut self, scope: &str, index_file: IndexFileEntry) -> Self { + self.packages + .entry(scope.to_string()) + .or_insert_with(|| (BTreeSet::new(), IndexFile::default())) + .1 + .push(index_file); + self + } +} + +impl Index for InMemoryIndex { + fn scope_owners(&self, scope: &str) -> Result, ScopeOwnersError> { + Ok(self.packages.get(scope).map(|(owners, _)| owners).cloned()) + } + + fn create_scope_for( + &mut self, + scope: &str, + owners: &ScopeOwners, + ) -> Result { + self.packages + .insert(scope.to_string(), (owners.clone(), IndexFile::default())); + Ok(true) + } + + fn package(&self, name: &PackageName) -> Result, IndexPackageError> { + Ok(self + .packages + .get(name.scope()) + .map(|(_, file)| file.clone())) + } + + fn create_package_version( + &mut self, + manifest: &Manifest, + uploader: &u64, + ) -> Result { + let scope = manifest.name.scope(); + + if let Some(owners) = self.scope_owners(scope)? { + if !owners.contains(uploader) { + return Err(CreatePackageVersionError::MissingScopeOwnership); + } + } else if !self.create_scope_for(scope, &BTreeSet::from([*uploader]))? { + return Err(CreatePackageVersionError::MissingScopeOwnership); + } + + let package = self.packages.get_mut(scope).unwrap(); + + package.1.push(manifest.clone().into()); + + Ok(true) + } + + fn config(&self) -> Result { + Ok(IndexConfig { + download: None, + api: "http://127.0.0.1:8080".to_string(), + github_oauth_client_id: "".to_string(), + custom_registry_allowed: false, + git_allowed: false, + }) + } + + fn credentials_fn(&self) -> Option<&Arc> { + None + } +} diff --git a/tests/resolver.rs b/tests/resolver.rs new file mode 100644 index 0000000..3bfb6e5 --- /dev/null +++ b/tests/resolver.rs @@ -0,0 +1,118 @@ +use std::collections::BTreeSet; + +use semver::Version; +use tempfile::tempdir; + +use pesde::{ + dependencies::{ + registry::{RegistryDependencySpecifier, RegistryPackageRef}, + resolution::ResolvedPackage, + DependencySpecifier, PackageRef, + }, + manifest::{DependencyType, Manifest, Realm}, + package_name::PackageName, + project::Project, +}; +use prelude::*; + +mod prelude; + +#[test] +fn test_resolves_package() { + let dir = tempdir().unwrap(); + let dir_path = dir.path().to_path_buf(); + let index = InMemoryIndex::new(); + + let version_str = "0.1.0"; + let version: Version = version_str.parse().unwrap(); + let version_2_str = "0.1.1"; + let version_2: Version = version_2_str.parse().unwrap(); + + let description = "test package"; + + let pkg_name = PackageName::new("test", "test").unwrap(); + + let pkg_manifest = Manifest { + name: pkg_name.clone(), + version: version.clone(), + exports: Default::default(), + path_style: Default::default(), + private: true, + realm: None, + dependencies: vec![], + peer_dependencies: vec![], + description: Some(description.to_string()), + license: None, + authors: None, + }; + + let mut pkg_2_manifest = pkg_manifest.clone(); + pkg_2_manifest.version = version_2.clone(); + + let index = index + .with_scope(pkg_name.scope(), BTreeSet::from([0])) + .with_package(pkg_name.scope(), pkg_manifest.into()) + .with_package(pkg_name.scope(), pkg_2_manifest.into()); + + let specifier = DependencySpecifier::Registry(RegistryDependencySpecifier { + name: pkg_name.clone(), + version: format!("={version_str}").parse().unwrap(), + realm: None, + }); + let specifier_2 = DependencySpecifier::Registry(RegistryDependencySpecifier { + name: pkg_name.clone(), + version: format!(">{version_str}").parse().unwrap(), + realm: None, + }); + + let user_manifest = Manifest { + name: "test/user".parse().unwrap(), + version: version.clone(), + exports: Default::default(), + path_style: Default::default(), + private: true, + realm: None, + dependencies: vec![specifier.clone()], + peer_dependencies: vec![specifier_2.clone()], + description: Some(description.to_string()), + license: None, + authors: None, + }; + + let project = Project::new(&dir_path, &dir_path, index, user_manifest, None); + + let tree = project.manifest().dependency_tree(&project, false).unwrap(); + assert_eq!(tree.len(), 1); + let versions = tree.get(&pkg_name).unwrap(); + assert_eq!(versions.len(), 2); + let resolved_pkg = versions.get(&version).unwrap(); + assert_eq!( + resolved_pkg, + &ResolvedPackage { + pkg_ref: PackageRef::Registry(RegistryPackageRef { + name: pkg_name.clone(), + version: version.clone(), + }), + specifier, + dependencies: Default::default(), + is_root: true, + realm: Realm::Shared, + dep_type: DependencyType::Normal, + } + ); + let resolved_pkg_2 = versions.get(&version_2).unwrap(); + assert_eq!( + resolved_pkg_2, + &ResolvedPackage { + pkg_ref: PackageRef::Registry(RegistryPackageRef { + name: pkg_name.clone(), + version: version_2.clone(), + }), + specifier: specifier_2, + dependencies: Default::default(), + is_root: true, + realm: Realm::Shared, + dep_type: DependencyType::Normal, + } + ); +}