diff --git a/.envrc b/.envrc new file mode 100644 index 0000000..3550a30 --- /dev/null +++ b/.envrc @@ -0,0 +1 @@ +use flake diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 0000000..6dac2af --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,9 @@ +version: 2 +updates: + - package-ecosystem: cargo + # Look for `Cargo.toml` and `Cargo.lock` in the root directory + directory: "/" + # Check for updates every Monday + schedule: + interval: weekly + open-pull-requests-limit: 2 diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..af00c37 --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,60 @@ +name: ci + +on: + pull_request: + push: + branches: + - main + +jobs: + check: + name: check + runs-on: ${{ matrix.os }} + strategy: + matrix: + os: [macos-latest, ubuntu-latest] + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Install nix + uses: cachix/install-nix-action@V27 + with: + extra_nix_config: access-tokens = github.com=${{ github.token }} + + - name: Check nix formatting + run: nix fmt -- -c . + + - name: Set up cachix + uses: cachix/cachix-action@v15 + with: + name: nix-community + + - name: Build with nix and run checks + run: | + nix flake check + + check-win: + name: "check windows" + runs-on: windows-latest + steps: + - name: Checkout + uses: actions/checkout@v4 + - name: Install Rust toolchain + uses: actions-rs/toolchain@v1 + with: + toolchain: stable + override: true + default: true + - name: Build + uses: actions-rs/cargo@v1 + with: + command: build + args: --release + + ci: + runs-on: ubuntu-latest + needs: [check, check-win] + steps: + - name: Aggregate of lint, and all tests + run: echo "ci passed" diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml new file mode 100644 index 0000000..30e1fd5 --- /dev/null +++ b/.github/workflows/publish.yml @@ -0,0 +1,281 @@ +name: Publish +on: + push: + tags: + - 'v*' + branches: + - main +jobs: + build: + runs-on: ubuntu-latest + strategy: + fail-fast: true + matrix: + build: + - aarch64 + - aarch64-musl + # - i686 + - amd64-musl + - amd64 + include: + - build: aarch64 + os: ubuntu-latest + target: aarch64-unknown-linux-gnu + use-cross: true + features: "--no-default-features --features rustls" + - build: aarch64-musl + os: ubuntu-latest + target: aarch64-unknown-linux-musl + use-cross: true + features: "--no-default-features --features rustls" + # - build: i686 + # os: ubuntu-latest + # target: i686-unknown-linux-gnu + # use-cross: true + # features: "--no-default-features --features rustls" + - build: amd64 + os: ubuntu-latest + target: x86_64-unknown-linux-gnu + use-cross: false + features: "" + - build: amd64-musl + os: ubuntu-latest + target: x86_64-unknown-linux-musl + use-cross: true + features: "--no-default-features --features rustls" + steps: + - uses: actions/checkout@3df4ab11eba7bda6032a0b82a6bb43b11571feac # v4 + with: + fetch-depth: 0 + + - name: Install prerequisites + shell: bash + run: | + sudo apt-get -y update + case ${{ matrix.target }} in + arm-unknown-linux-gnueabihf) sudo apt-get -y install gcc-arm-linux-gnueabihf ;; + aarch64-unknown-linux-gnu) sudo apt-get -y install gcc-aarch64-linux-gnu ;; + aarch64-unknown-linux-musl) sudo apt-get -y install gcc-aarch64-linux-gnu ;; + esac + sudo apt-get -y install libssl-dev openssl pkg-config + + - name: Extract crate information + shell: bash + run: | + echo "PROJECT_NAME=$(sed -n 's/^name = "\(.*\)"/\1/p' Cargo.toml | head -n1)" >> $GITHUB_ENV + echo "PROJECT_MAINTAINER=$(sed -n 's/^authors = \["\(.*\)"\]/\1/p' Cargo.toml)" >> $GITHUB_ENV + echo "PROJECT_HOMEPAGE=$(sed -n 's/^homepage = "\(.*\)"/\1/p' Cargo.toml)" >> $GITHUB_ENV + PROJECT_VERSION="$(sed -n 's/^version = "\(.*\)"/\1/p' Cargo.toml | head -n1)" + echo "PROJECT_VERSION=$PROJECT_VERSION" >> $GITHUB_ENV + if [[ $PROJECT_VERSION == *-pre ]]; then + echo "VERSION_SUFFIX=nightly" >> $GITHUB_ENV + else + echo "VERSION_SUFFIX=$PROJECT_VERSION" >> $GITHUB_ENV + fi + + - name: Install Rust toolchain + uses: actions-rs/toolchain@v1 + with: + toolchain: stable + target: ${{ matrix.target }} + override: true + default: true + + - name: Show version information (Rust, cargo, GCC) + shell: bash + run: | + gcc --version || true + rustup -V + rustup toolchain list + rustup default + cargo -V + rustc -V + - name: Build + uses: actions-rs/cargo@v1 + with: + use-cross: ${{ matrix.use-cross }} + command: build + args: ${{ matrix.features }} --release --target=${{ matrix.target }} + + - name: Strip debug information from executable + id: strip + shell: bash + run: | + # Figure out what strip tool to use if any + STRIP="strip" + case ${{ matrix.target }} in + arm-unknown-linux-gnueabihf) STRIP="arm-linux-gnueabihf-strip" ;; + aarch64-unknown-linux-gnu) STRIP="aarch64-linux-gnu-strip" ;; + aarch64-unknown-linux-musl) STRIP="aarch64-linux-gnu-strip" ;; + *-pc-windows-msvc) STRIP="" ;; + esac; + # Setup paths + BIN_DIR="_cicd/stripped-release-bin/" + mkdir -p "${BIN_DIR}" + BIN_NAME="${{ env.PROJECT_NAME }}" + BIN_PATH="${BIN_DIR}/${BIN_NAME}_${{ matrix.build }}-${{ env.VERSION_SUFFIX }}" + # Copy the release build binary to the result location + cp "target/${{ matrix.target }}/release/${BIN_NAME}" "${BIN_PATH}" + # Also strip if possible + if [ -n "${STRIP}" ]; then + "${STRIP}" "${BIN_PATH}" + fi + # Let subsequent steps know where to find the (stripped) bin + echo "BIN_PATH=${BIN_PATH}" >> $GITHUB_OUTPUT + + - name: Publish Release + id: publish + uses: softprops/action-gh-release@v1 + if: startsWith(github.ref, 'refs/tags/') + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + with: + files: | + ${{ steps.strip.outputs.BIN_PATH }} + + - name: Publish Pre-Release + id: publish-pre + if: ${{ github.ref }} == 'refs/heads/main' + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + uses: "ncipollo/release-action@v1" + with: + token: "${{ secrets.GITHUB_TOKEN }}" + prerelease: true + allowUpdates: true + tag: "nightly" + commit: "main" + name: "renku-cli nightly" + replacesArtifacts: true + artifacts: ${{ steps.strip.outputs.BIN_PATH }} + + build-win: + runs-on: windows-latest + + steps: + - name: Checkout + uses: actions/checkout@3df4ab11eba7bda6032a0b82a6bb43b11571feac # v4 + with: + fetch-depth: 0 + + - name: Install Rust toolchain + uses: actions-rs/toolchain@v1 + with: + toolchain: stable + override: true + default: true + + - name: Extract crate information + shell: bash + run: | + echo "PROJECT_NAME=$(sed -n 's/^name = "\(.*\)"/\1/p' Cargo.toml | head -n1)" >> $GITHUB_ENV + PROJECT_VERSION="$(sed -n 's/^version = "\(.*\)"/\1/p' Cargo.toml | head -n1)" + echo "PROJECT_VERSION=$PROJECT_VERSION" >> $GITHUB_ENV + if [[ $PROJECT_VERSION == *-pre ]]; then + echo "VERSION_SUFFIX=nightly" >> $GITHUB_ENV + else + echo "VERSION_SUFFIX=$PROJECT_VERSION" >> $GITHUB_ENV + fi + + - name: Build + uses: actions-rs/cargo@v1 + with: + command: build + args: ${{ matrix.features }} --release + + - name: Rename binary + run: | + mv target/release/${{ env.PROJECT_NAME }}.exe target/release/${{ env.PROJECT_NAME }}-${{ env.VERSION_SUFFIX }}.exe + + - name: Publish Release + id: publish + uses: softprops/action-gh-release@v1 + if: startsWith(github.ref, 'refs/tags/') + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + with: + files: | + target/release/${{ env.PROJECT_NAME }}-${{ env.VERSION_SUFFIX }}.exe + + - name: Publish Pre-Release + id: publish-pre + if: ${{ github.ref }} == 'refs/heads/main' + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + uses: "ncipollo/release-action@v1" + with: + token: "${{ secrets.GITHUB_TOKEN }}" + prerelease: true + allowUpdates: true + tag: "nightly" + commit: "main" + name: "renku-cli nightly" + replacesArtifacts: true + artifacts: target/release/${{ env.PROJECT_NAME }}-${{ env.VERSION_SUFFIX }}.exe + + build-mac: + runs-on: macos-latest + + steps: + - name: Checkout + uses: actions/checkout@3df4ab11eba7bda6032a0b82a6bb43b11571feac # v4 + with: + fetch-depth: 0 + + - name: Install Rust toolchain + uses: actions-rs/toolchain@v1 + with: + toolchain: stable + target: x86_64-apple-darwin + override: true + default: true + + - name: Extract crate information + shell: bash + run: | + echo "PROJECT_NAME=$(sed -n 's/^name = "\(.*\)"/\1/p' Cargo.toml | head -n1)" >> $GITHUB_ENV + PROJECT_VERSION="$(sed -n 's/^version = "\(.*\)"/\1/p' Cargo.toml | head -n1)" + echo "PROJECT_VERSION=$PROJECT_VERSION" >> $GITHUB_ENV + if [[ $PROJECT_VERSION == *-pre ]]; then + echo "VERSION_SUFFIX=nightly" >> $GITHUB_ENV + else + echo "VERSION_SUFFIX=$PROJECT_VERSION" >> $GITHUB_ENV + fi + + - name: Build + uses: actions-rs/cargo@v1 + with: + command: build + args: ${{ matrix.features }} --release + + - name: Rename and strip binary + run: | + strip target/release/${{ env.PROJECT_NAME }} + mv target/release/${{ env.PROJECT_NAME }} target/release/${{ env.PROJECT_NAME }}_darwin-${{ env.VERSION_SUFFIX }} + + - name: Publish Release + id: publish + uses: softprops/action-gh-release@v1 + if: startsWith(github.ref, 'refs/tags/') + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + with: + prerelease: ${{ github.ref }} == "refs/heads/main" + files: | + target/release/${{ env.PROJECT_NAME }}_darwin-${{ env.VERSION_SUFFIX }} + + - name: Publish Pre-Release + id: publish-pre + if: ${{ github.ref }} == 'refs/heads/main' + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + uses: "ncipollo/release-action@v1" + with: + token: "${{ secrets.GITHUB_TOKEN }}" + prerelease: true + allowUpdates: true + tag: "nightly" + commit: "main" + name: "renku-cli nightly" + replacesArtifacts: true + artifacts: target/release/${{ env.PROJECT_NAME }}_darwin-${{ env.VERSION_SUFFIX }} diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..81ebc2c --- /dev/null +++ b/.gitignore @@ -0,0 +1,6 @@ +/target +result* +/local +*.qcow2 +.direnv/ +.vscode diff --git a/Cargo.lock b/Cargo.lock new file mode 100644 index 0000000..0695b61 --- /dev/null +++ b/Cargo.lock @@ -0,0 +1,1887 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "addr2line" +version = "0.22.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6e4503c46a5c0c7844e948c9a4d6acd9f50cccb4de1c48eb9e291ea17470c678" +dependencies = [ + "gimli", +] + +[[package]] +name = "adler" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" + +[[package]] +name = "aho-corasick" +version = "1.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916" +dependencies = [ + "memchr", +] + +[[package]] +name = "anstream" +version = "0.6.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "418c75fa768af9c03be99d17643f93f79bbba589895012a80e3452a19ddda15b" +dependencies = [ + "anstyle", + "anstyle-parse", + "anstyle-query", + "anstyle-wincon", + "colorchoice", + "is_terminal_polyfill", + "utf8parse", +] + +[[package]] +name = "anstyle" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "038dfcf04a5feb68e9c60b21c9625a54c2c0616e79b72b0fd87075a056ae1d1b" + +[[package]] +name = "anstyle-parse" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c03a11a9034d92058ceb6ee011ce58af4a9bf61491aa7e1e59ecd24bd40d22d4" +dependencies = [ + "utf8parse", +] + +[[package]] +name = "anstyle-query" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ad186efb764318d35165f1758e7dcef3b10628e26d41a44bc5550652e6804391" +dependencies = [ + "windows-sys 0.52.0", +] + +[[package]] +name = "anstyle-wincon" +version = "3.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "61a38449feb7068f52bb06c12759005cf459ee52bb4adc1d5a7c4322d716fb19" +dependencies = [ + "anstyle", + "windows-sys 0.52.0", +] + +[[package]] +name = "anyhow" +version = "1.0.86" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b3d1d046238990b9cf5bcde22a3fb3584ee5cf65fb2765f454ed428c7a0063da" + +[[package]] +name = "assert_cmd" +version = "2.0.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed72493ac66d5804837f480ab3766c72bdfab91a65e565fc54fa9e42db0073a8" +dependencies = [ + "anstyle", + "bstr", + "doc-comment", + "predicates", + "predicates-core", + "predicates-tree", + "wait-timeout", +] + +[[package]] +name = "autocfg" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c4b4d0bd25bd0b74681c0ad21497610ce1b7c91b1022cd21c80c6fbdd9476b0" + +[[package]] +name = "backtrace" +version = "0.3.73" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5cc23269a4f8976d0a4d2e7109211a419fe30e8d88d677cd60b6bc79c5732e0a" +dependencies = [ + "addr2line", + "cc", + "cfg-if", + "libc", + "miniz_oxide", + "object", + "rustc-demangle", +] + +[[package]] +name = "base64" +version = "0.22.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" + +[[package]] +name = "bitflags" +version = "2.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de" + +[[package]] +name = "bstr" +version = "1.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05efc5cfd9110c8416e471df0e96702d58690178e206e61b7173706673c93706" +dependencies = [ + "memchr", + "regex-automata", + "serde", +] + +[[package]] +name = "bumpalo" +version = "3.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "79296716171880943b8470b5f8d03aa55eb2e645a4874bdbb28adb49162e012c" + +[[package]] +name = "bytes" +version = "1.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "514de17de45fdb8dc022b1a7975556c53c86f9f0aa5f534b98977b171857c2c9" + +[[package]] +name = "camino" +version = "1.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e0ec6b951b160caa93cc0c7b209e5a3bff7aae9062213451ac99493cd844c239" +dependencies = [ + "serde", +] + +[[package]] +name = "cargo-platform" +version = "0.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "24b1f0365a6c6bb4020cd05806fd0d33c44d38046b8bd7f0e40814b9763cabfc" +dependencies = [ + "serde", +] + +[[package]] +name = "cargo_metadata" +version = "0.18.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2d886547e41f740c616ae73108f6eb70afe6d940c7bc697cb30f13daec073037" +dependencies = [ + "camino", + "cargo-platform", + "semver", + "serde", + "serde_json", + "thiserror", +] + +[[package]] +name = "cc" +version = "1.0.101" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac367972e516d45567c7eafc73d24e1c193dcf200a8d94e9db7b3d38b349572d" + +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + +[[package]] +name = "clap" +version = "4.5.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5db83dced34638ad474f39f250d7fea9598bdd239eaced1bdf45d597da0f433f" +dependencies = [ + "clap_builder", + "clap_derive", +] + +[[package]] +name = "clap_builder" +version = "4.5.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f7e204572485eb3fbf28f871612191521df159bc3e15a9f5064c66dba3a8c05f" +dependencies = [ + "anstream", + "anstyle", + "clap_lex", + "strsim", + "terminal_size", +] + +[[package]] +name = "clap_complete" +version = "4.5.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fbca90c87c2a04da41e95d1856e8bcd22f159bdbfa147314d2ce5218057b0e58" +dependencies = [ + "clap", +] + +[[package]] +name = "clap_derive" +version = "4.5.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c780290ccf4fb26629baa7a1081e68ced113f1d3ec302fa5948f1c381ebf06c6" +dependencies = [ + "heck", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "clap_lex" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4b82cf0babdbd58558212896d1a4272303a57bdb245c2bf1147185fb45640e70" + +[[package]] +name = "colorchoice" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b6a852b24ab71dffc585bcb46eaf7959d175cb865a7152e35b348d1b2960422" + +[[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 = "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 = "deranged" +version = "0.3.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b42b6fa04a440b495c8b04d0e71b707c585f83cb9cb28cf8cd0d976c315e31b4" +dependencies = [ + "powerfmt", +] + +[[package]] +name = "difflib" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6184e33543162437515c2e2b48714794e37845ec9851711914eec9d308f6ebe8" + +[[package]] +name = "doc-comment" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fea41bba32d969b513997752735605054bc0dfa92b4c56bf1189f2e174be7a10" + +[[package]] +name = "encode_unicode" +version = "0.3.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a357d28ed41a50f9c765dbfe56cbc04a64e53e5fc58ba79fbc34c10ef3df831f" + +[[package]] +name = "env_filter" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a009aa4810eb158359dda09d0c87378e4bbb89b5a801f016885a4707ba24f7ea" +dependencies = [ + "log", + "regex", +] + +[[package]] +name = "env_logger" +version = "0.11.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38b35839ba51819680ba087cd351788c9a3c476841207e0b8cee0b04722343b9" +dependencies = [ + "anstream", + "anstyle", + "env_filter", + "humantime", + "log", +] + +[[package]] +name = "errno" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "534c5cf6194dfab3db3242765c03bbe257cf92f22b38f6bc0c58d59108a820ba" +dependencies = [ + "libc", + "windows-sys 0.52.0", +] + +[[package]] +name = "fastrand" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9fc0510504f03c51ada170672ac806f1f105a88aa97a5281117e1ddc3368e51a" + +[[package]] +name = "float-cmp" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "98de4bbd547a563b716d8dfa9aad1cb19bfab00f4fa09a6a4ed21dbcf44ce9c4" +dependencies = [ + "num-traits", +] + +[[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-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-io" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a44623e20b9681a318efdd71c299b6b222ed6f231972bfe2f224ebad6311f0c1" + +[[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-sink", + "futures-task", + "memchr", + "pin-project-lite", + "pin-utils", + "slab", +] + +[[package]] +name = "getrandom" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7" +dependencies = [ + "cfg-if", + "libc", + "wasi", +] + +[[package]] +name = "gimli" +version = "0.29.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "40ecd4077b5ae9fd2e9e169b102c6c330d0605168eb0e8bf79952b256dbefffd" + +[[package]] +name = "heck" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" + +[[package]] +name = "http" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "21b9ddb458710bc376481b842f5da65cdf31522de232c1ca8146abce2a358258" +dependencies = [ + "bytes", + "fnv", + "itoa", +] + +[[package]] +name = "http-body" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1cac85db508abc24a2e48553ba12a996e87244a0395ce011e62b37158745d643" +dependencies = [ + "bytes", + "http", +] + +[[package]] +name = "http-body-util" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "793429d76616a256bcb62c2a2ec2bed781c8307e797e2598c50010f2bee2544f" +dependencies = [ + "bytes", + "futures-util", + "http", + "http-body", + "pin-project-lite", +] + +[[package]] +name = "httparse" +version = "1.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fcc0b4a115bf80b728eb8ea024ad5bd707b615bfed49e0665b6e0f86fd082d9" + +[[package]] +name = "humantime" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4" + +[[package]] +name = "hyper" +version = "1.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fe575dd17d0862a9a33781c8c4696a55c320909004a67a00fb286ba8b1bc496d" +dependencies = [ + "bytes", + "futures-channel", + "futures-util", + "http", + "http-body", + "httparse", + "itoa", + "pin-project-lite", + "smallvec", + "tokio", + "want", +] + +[[package]] +name = "hyper-rustls" +version = "0.27.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5ee4be2c948921a1a5320b629c4193916ed787a7f7f293fd3f7f5a6c9de74155" +dependencies = [ + "futures-util", + "http", + "hyper", + "hyper-util", + "rustls", + "rustls-pki-types", + "tokio", + "tokio-rustls", + "tower-service", + "webpki-roots", +] + +[[package]] +name = "hyper-tls" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "70206fc6890eaca9fde8a0bf71caa2ddfc9fe045ac9e5c70df101a7dbde866e0" +dependencies = [ + "bytes", + "http-body-util", + "hyper", + "hyper-util", + "native-tls", + "tokio", + "tokio-native-tls", + "tower-service", +] + +[[package]] +name = "hyper-util" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7b875924a60b96e5d7b9ae7b066540b1dd1cbd90d1828f54c92e02a283351c56" +dependencies = [ + "bytes", + "futures-channel", + "futures-util", + "http", + "http-body", + "hyper", + "pin-project-lite", + "socket2", + "tokio", + "tower", + "tower-service", + "tracing", +] + +[[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 = "ipnet" +version = "2.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f518f335dce6725a761382244631d86cf0ccb2863413590b31338feb467f9c3" + +[[package]] +name = "is_terminal_polyfill" +version = "1.70.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8478577c03552c21db0e2724ffb8986a5ce7af88107e6be5d2ee6e158c12800" + +[[package]] +name = "itoa" +version = "1.0.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b" + +[[package]] +name = "js-sys" +version = "0.3.69" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "29c15563dc2726973df627357ce0c9ddddbea194836909d655df6a75d2cf296d" +dependencies = [ + "wasm-bindgen", +] + +[[package]] +name = "lazy_static" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" + +[[package]] +name = "libc" +version = "0.2.155" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "97b3888a4aecf77e811145cadf6eef5901f4782c53886191b2f693f24761847c" + +[[package]] +name = "linux-raw-sys" +version = "0.4.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "78b3ae25bc7c8c38cec158d1f2757ee79e9b3740fbc7ccf0e59e4b08d793fa89" + +[[package]] +name = "log" +version = "0.4.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "90ed8c1e510134f979dbc4f070f87d4313098b704861a105fe34231c70a3901c" + +[[package]] +name = "memchr" +version = "2.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" + +[[package]] +name = "mime" +version = "0.3.17" +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 = "miniz_oxide" +version = "0.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8a240ddb74feaf34a79a7add65a741f3167852fba007066dcac1ca548d89c08" +dependencies = [ + "adler", +] + +[[package]] +name = "mio" +version = "0.8.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4a650543ca06a924e8b371db273b2756685faae30f8487da1b56505a8f78b0c" +dependencies = [ + "libc", + "wasi", + "windows-sys 0.48.0", +] + +[[package]] +name = "native-tls" +version = "0.2.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a8614eb2c83d59d1c8cc974dd3f920198647674a0a035e1af1fa58707e317466" +dependencies = [ + "libc", + "log", + "openssl", + "openssl-probe", + "openssl-sys", + "schannel", + "security-framework", + "security-framework-sys", + "tempfile", +] + +[[package]] +name = "normalize-line-endings" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "61807f77802ff30975e01f4f071c8ba10c022052f98b3294119f3e615d13e5be" + +[[package]] +name = "num-conv" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "51d515d32fb182ee37cda2ccdcb92950d6a3c2893aa280e540671c2cd0f3b1d9" + +[[package]] +name = "num-traits" +version = "0.2.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" +dependencies = [ + "autocfg", +] + +[[package]] +name = "num_threads" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c7398b9c8b70908f6371f47ed36737907c87c52af34c268fed0bf0ceb92ead9" +dependencies = [ + "libc", +] + +[[package]] +name = "object" +version = "0.36.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "576dfe1fc8f9df304abb159d767a29d0476f7750fbf8aa7ad07816004a207434" +dependencies = [ + "memchr", +] + +[[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.64" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95a0481286a310808298130d22dd1fef0fa571e05a8f44ec801801e84b216b1f" +dependencies = [ + "bitflags", + "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", +] + +[[package]] +name = "openssl-probe" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf" + +[[package]] +name = "openssl-src" +version = "300.3.1+3.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7259953d42a81bf137fbbd73bd30a8e1914d6dce43c2b90ed575783a22608b91" +dependencies = [ + "cc", +] + +[[package]] +name = "openssl-sys" +version = "0.9.102" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c597637d56fbc83893a35eb0dd04b2b8e7a50c91e64e9493e398b5df4fb45fa2" +dependencies = [ + "cc", + "libc", + "openssl-src", + "pkg-config", + "vcpkg", +] + +[[package]] +name = "percent-encoding" +version = "2.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" + +[[package]] +name = "pin-project" +version = "1.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6bf43b791c5b9e34c3d182969b4abb522f9343702850a2e57f460d00d09b4b3" +dependencies = [ + "pin-project-internal", +] + +[[package]] +name = "pin-project-internal" +version = "1.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2f38a4412a78282e09a2cf38d195ea5420d15ba0602cb375210efbc877243965" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "pin-project-lite" +version = "0.2.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bda66fc9667c18cb2758a2ac84d1167245054bcf85d5d1aaa6923f45801bdd02" + +[[package]] +name = "pin-utils" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" + +[[package]] +name = "pkg-config" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d231b230927b5e4ad203db57bbcbee2802f6bce620b1e4a9024a07d94e2907ec" + +[[package]] +name = "powerfmt" +version = "0.2.0" +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 = "predicates" +version = "3.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68b87bfd4605926cdfefc1c3b5f8fe560e3feca9d5552cf68c466d3d8236c7e8" +dependencies = [ + "anstyle", + "difflib", + "float-cmp", + "normalize-line-endings", + "predicates-core", + "regex", +] + +[[package]] +name = "predicates-core" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b794032607612e7abeb4db69adb4e33590fa6cf1149e95fd7cb00e634b92f174" + +[[package]] +name = "predicates-tree" +version = "1.0.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "368ba315fb8c5052ab692e68a0eefec6ec57b23a36959c14496f0b0df2c0cecf" +dependencies = [ + "predicates-core", + "termtree", +] + +[[package]] +name = "proc-macro2" +version = "1.0.86" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5e719e8df665df0d1c8fbfd238015744736151d4445ec0836b8e628aae103b77" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "quinn" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e4ceeeeabace7857413798eb1ffa1e9c905a9946a57d81fb69b4b71c4d8eb3ad" +dependencies = [ + "bytes", + "pin-project-lite", + "quinn-proto", + "quinn-udp", + "rustc-hash", + "rustls", + "thiserror", + "tokio", + "tracing", +] + +[[package]] +name = "quinn-proto" +version = "0.11.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ddf517c03a109db8100448a4be38d498df8a210a99fe0e1b9eaf39e78c640efe" +dependencies = [ + "bytes", + "rand", + "ring", + "rustc-hash", + "rustls", + "slab", + "thiserror", + "tinyvec", + "tracing", +] + +[[package]] +name = "quinn-udp" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9096629c45860fc7fb143e125eb826b5e721e10be3263160c7d60ca832cf8c46" +dependencies = [ + "libc", + "once_cell", + "socket2", + "tracing", + "windows-sys 0.52.0", +] + +[[package]] +name = "quote" +version = "1.0.36" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fa76aaf39101c457836aec0ce2316dbdc3ab723cdda1c6bd4e6ad4208acaca7" +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 = "regex" +version = "1.10.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b91213439dad192326a0d7c6ee3955910425f441d7038e0d6933b0aec5c4517f" +dependencies = [ + "aho-corasick", + "memchr", + "regex-automata", + "regex-syntax", +] + +[[package]] +name = "regex-automata" +version = "0.4.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38caf58cc5ef2fed281f89292ef23f6365465ed9a41b7a7754eb4e26496c92df" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax", +] + +[[package]] +name = "regex-syntax" +version = "0.8.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a66a03ae7c801facd77a29370b4faec201768915ac14a721ba36f20bc9c209b" + +[[package]] +name = "renku-cli" +version = "0.1.0-nightly" +dependencies = [ + "assert_cmd", + "clap", + "clap_complete", + "console", + "env_logger", + "log", + "openssl", + "predicates", + "reqwest", + "serde", + "serde_json", + "snafu", + "vergen", +] + +[[package]] +name = "reqwest" +version = "0.12.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c7d6d2a27d57148378eb5e111173f4276ad26340ecc5c49a4a2152167a2d6a37" +dependencies = [ + "base64", + "bytes", + "futures-channel", + "futures-core", + "futures-util", + "http", + "http-body", + "http-body-util", + "hyper", + "hyper-rustls", + "hyper-tls", + "hyper-util", + "ipnet", + "js-sys", + "log", + "mime", + "mime_guess", + "native-tls", + "once_cell", + "percent-encoding", + "pin-project-lite", + "quinn", + "rustls", + "rustls-pemfile", + "rustls-pki-types", + "serde", + "serde_json", + "serde_urlencoded", + "sync_wrapper", + "tokio", + "tokio-native-tls", + "tokio-rustls", + "tower-service", + "url", + "wasm-bindgen", + "wasm-bindgen-futures", + "web-sys", + "webpki-roots", + "winreg", +] + +[[package]] +name = "ring" +version = "0.17.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c17fa4cb658e3583423e915b9f3acc01cceaee1860e33d59ebae66adc3a2dc0d" +dependencies = [ + "cc", + "cfg-if", + "getrandom", + "libc", + "spin", + "untrusted", + "windows-sys 0.52.0", +] + +[[package]] +name = "rustc-demangle" +version = "0.1.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f" + +[[package]] +name = "rustc-hash" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" + +[[package]] +name = "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.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "70dc5ec042f7a43c4a73241207cecc9873a06d45debb38b329f8541d85c2730f" +dependencies = [ + "bitflags", + "errno", + "libc", + "linux-raw-sys", + "windows-sys 0.52.0", +] + +[[package]] +name = "rustls" +version = "0.23.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05cff451f60db80f490f3c182b77c35260baace73209e9cdbbe526bfe3a4d402" +dependencies = [ + "once_cell", + "ring", + "rustls-pki-types", + "rustls-webpki", + "subtle", + "zeroize", +] + +[[package]] +name = "rustls-pemfile" +version = "2.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "29993a25686778eb88d4189742cd713c9bce943bc54251a33509dc63cbacf73d" +dependencies = [ + "base64", + "rustls-pki-types", +] + +[[package]] +name = "rustls-pki-types" +version = "1.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "976295e77ce332211c0d24d92c0e83e50f5c5f046d11082cea19f3df13a3562d" + +[[package]] +name = "rustls-webpki" +version = "0.102.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ff448f7e92e913c4b7d4c6d8e4540a1724b319b4152b8aef6d4cf8339712b33e" +dependencies = [ + "ring", + "rustls-pki-types", + "untrusted", +] + +[[package]] +name = "rustversion" +version = "1.0.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "955d28af4278de8121b7ebeb796b6a45735dc01436d898801014aced2773a3d6" + +[[package]] +name = "ryu" +version = "1.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f" + +[[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 = "security-framework" +version = "2.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c627723fd09706bacdb5cf41499e95098555af3c3c29d014dc3c458ef6be11c0" +dependencies = [ + "bitflags", + "core-foundation", + "core-foundation-sys", + "libc", + "security-framework-sys", +] + +[[package]] +name = "security-framework-sys" +version = "2.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "317936bbbd05227752583946b9e66d7ce3b489f84e11a94a510b4437fef407d7" +dependencies = [ + "core-foundation-sys", + "libc", +] + +[[package]] +name = "semver" +version = "1.0.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "61697e0a1c7e512e84a621326239844a24d8207b4669b41bc18b32ea5cbf988b" +dependencies = [ + "serde", +] + +[[package]] +name = "serde" +version = "1.0.203" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7253ab4de971e72fb7be983802300c30b5a7f0c2e56fab8abfc6a214307c0094" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.203" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "500cbc0ebeb6f46627f50f3f5811ccf6bf00643be300b4c3eabc0ef55dc5b5ba" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "serde_json" +version = "1.0.118" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d947f6b3163d8857ea16c4fa0dd4840d52f3041039a85decd46867eb1abef2e4" +dependencies = [ + "itoa", + "ryu", + "serde", +] + +[[package]] +name = "serde_urlencoded" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3491c14715ca2294c4d6a88f15e84739788c1d030eed8c110436aafdaa2f3fd" +dependencies = [ + "form_urlencoded", + "itoa", + "ryu", + "serde", +] + +[[package]] +name = "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.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" + +[[package]] +name = "snafu" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "418b8136fec49956eba89be7da2847ec1909df92a9ae4178b5ff0ff092c8d95e" +dependencies = [ + "snafu-derive", +] + +[[package]] +name = "snafu-derive" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a4812a669da00d17d8266a0439eddcacbc88b17f732f927e52eeb9d196f7fb5" +dependencies = [ + "heck", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "socket2" +version = "0.5.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ce305eb0b4296696835b71df73eb912e0f1ffd2556a501fcede6e0c50349191c" +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 = "strsim" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" + +[[package]] +name = "subtle" +version = "2.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" + +[[package]] +name = "syn" +version = "2.0.68" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "901fa70d88b9d6c98022e23b4136f9f3e54e4662c3bc1bd1d84a42a9a0f0c1e9" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "sync_wrapper" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a7065abeca94b6a8a577f9bd45aa0867a2238b74e8eb67cf10d492bc39351394" + +[[package]] +name = "tempfile" +version = "3.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85b77fafb263dd9d05cbeac119526425676db3784113aa9295c88498cbf8bff1" +dependencies = [ + "cfg-if", + "fastrand", + "rustix", + "windows-sys 0.52.0", +] + +[[package]] +name = "terminal_size" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "21bebf2b7c9e0a515f6e0f8c51dc0f8e4696391e6f1ff30379559f8365fb0df7" +dependencies = [ + "rustix", + "windows-sys 0.48.0", +] + +[[package]] +name = "termtree" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3369f5ac52d5eb6ab48c6b4ffdc8efbcad6b89c765749064ba298f2c68a16a76" + +[[package]] +name = "thiserror" +version = "1.0.61" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c546c80d6be4bc6a00c0f01730c08df82eaa7a7a61f11d656526506112cc1709" +dependencies = [ + "thiserror-impl", +] + +[[package]] +name = "thiserror-impl" +version = "1.0.61" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "46c3384250002a6d5af4d114f2845d37b57521033f30d5c3f46c4d70e1197533" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "time" +version = "0.3.36" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5dfd88e563464686c916c7e46e623e520ddc6d79fa6641390f2e3fa86e83e885" +dependencies = [ + "deranged", + "itoa", + "libc", + "num-conv", + "num_threads", + "powerfmt", + "serde", + "time-core", + "time-macros", +] + +[[package]] +name = "time-core" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ef927ca75afb808a4d64dd374f00a2adf8d0fcff8e7b184af886c3c87ec4a3f3" + +[[package]] +name = "time-macros" +version = "0.2.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f252a68540fde3a3877aeea552b832b40ab9a69e318efd078774a01ddee1ccf" +dependencies = [ + "num-conv", + "time-core", +] + +[[package]] +name = "tinyvec" +version = "1.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c55115c6fbe2d2bef26eb09ad74bde02d8255476fc0c7b515ef09fbb35742d82" +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.38.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba4f4a02a7a80d6f274636f0aa95c7e383b912d41fe721a31f29e29698585a4a" +dependencies = [ + "backtrace", + "bytes", + "libc", + "mio", + "pin-project-lite", + "socket2", + "windows-sys 0.48.0", +] + +[[package]] +name = "tokio-native-tls" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbae76ab933c85776efabc971569dd6119c580d8f5d448769dec1764bf796ef2" +dependencies = [ + "native-tls", + "tokio", +] + +[[package]] +name = "tokio-rustls" +version = "0.26.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c7bc40d0e5a97695bb96e27995cd3a08538541b0a846f65bba7a359f36700d4" +dependencies = [ + "rustls", + "rustls-pki-types", + "tokio", +] + +[[package]] +name = "tower" +version = "0.4.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8fa9be0de6cf49e536ce1851f987bd21a43b771b09473c3549a6c853db37c1c" +dependencies = [ + "futures-core", + "futures-util", + "pin-project", + "pin-project-lite", + "tokio", + "tower-layer", + "tower-service", +] + +[[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 = [ + "pin-project-lite", + "tracing-attributes", + "tracing-core", +] + +[[package]] +name = "tracing-attributes" +version = "0.1.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "tracing-core" +version = "0.1.32" +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 = "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-width" +version = "0.1.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0336d538f7abc86d282a4189614dfaa90810dfc2c6f6427eaf88e16311dd225d" + +[[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.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "22784dbdf76fdde8af1aeda5622b546b422b6fc585325248a2bf9f5e41e94d6c" +dependencies = [ + "form_urlencoded", + "idna", + "percent-encoding", +] + +[[package]] +name = "utf8parse" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" + +[[package]] +name = "vcpkg" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" + +[[package]] +name = "vergen" +version = "8.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e27d6bdd219887a9eadd19e1c34f32e47fa332301184935c6d9bca26f3cca525" +dependencies = [ + "anyhow", + "cargo_metadata", + "cfg-if", + "regex", + "rustc_version", + "rustversion", + "time", +] + +[[package]] +name = "version_check" +version = "0.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" + +[[package]] +name = "wait-timeout" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9f200f5b12eb75f8c1ed65abd4b2db8a6e1b138a20de009dacee265a2498f3f6" +dependencies = [ + "libc", +] + +[[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.92" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4be2531df63900aeb2bca0daaaddec08491ee64ceecbee5076636a3b026795a8" +dependencies = [ + "cfg-if", + "wasm-bindgen-macro", +] + +[[package]] +name = "wasm-bindgen-backend" +version = "0.2.92" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "614d787b966d3989fa7bb98a654e369c762374fd3213d212cfc0251257e747da" +dependencies = [ + "bumpalo", + "log", + "once_cell", + "proc-macro2", + "quote", + "syn", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-futures" +version = "0.4.42" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "76bc14366121efc8dbb487ab05bcc9d346b3b5ec0eaa76e46594cabbe51762c0" +dependencies = [ + "cfg-if", + "js-sys", + "wasm-bindgen", + "web-sys", +] + +[[package]] +name = "wasm-bindgen-macro" +version = "0.2.92" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1f8823de937b71b9460c0c34e25f3da88250760bec0ebac694b49997550d726" +dependencies = [ + "quote", + "wasm-bindgen-macro-support", +] + +[[package]] +name = "wasm-bindgen-macro-support" +version = "0.2.92" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e94f17b526d0a461a191c78ea52bbce64071ed5c04c9ffe424dcb38f74171bb7" +dependencies = [ + "proc-macro2", + "quote", + "syn", + "wasm-bindgen-backend", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-shared" +version = "0.2.92" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "af190c94f2773fdb3729c55b007a722abb5384da03bc0986df4c289bf5567e96" + +[[package]] +name = "web-sys" +version = "0.3.69" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77afa9a11836342370f4817622a2f0f418b134426d91a82dfb48f532d2ec13ef" +dependencies = [ + "js-sys", + "wasm-bindgen", +] + +[[package]] +name = "webpki-roots" +version = "0.26.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bd7c23921eeb1713a4e851530e9b9756e4fb0e89978582942612524cf09f01cd" +dependencies = [ + "rustls-pki-types", +] + +[[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.5", +] + +[[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.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6f0713a46559409d202e70e28227288446bf7841d3211583a4b53e3f6d96e7eb" +dependencies = [ + "windows_aarch64_gnullvm 0.52.5", + "windows_aarch64_msvc 0.52.5", + "windows_i686_gnu 0.52.5", + "windows_i686_gnullvm", + "windows_i686_msvc 0.52.5", + "windows_x86_64_gnu 0.52.5", + "windows_x86_64_gnullvm 0.52.5", + "windows_x86_64_msvc 0.52.5", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7088eed71e8b8dda258ecc8bac5fb1153c5cffaf2578fc8ff5d61e23578d3263" + +[[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.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9985fd1504e250c615ca5f281c3f7a6da76213ebd5ccc9561496568a2752afb6" + +[[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.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "88ba073cf16d5372720ec942a8ccbf61626074c6d4dd2e745299726ce8b89670" + +[[package]] +name = "windows_i686_gnullvm" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87f4261229030a858f36b459e748ae97545d6f1ec60e5e0d6a3d32e0dc232ee9" + +[[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.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "db3c2bf3d13d5b658be73463284eaf12830ac9a26a90c717b7f771dfe97487bf" + +[[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.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4e4246f76bdeff09eb48875a0fd3e2af6aada79d409d33011886d3e1581517d9" + +[[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.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "852298e482cd67c356ddd9570386e2862b5673c85bd5f88df9ab6802b334c596" + +[[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.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bec47e5bfd1bff0eeaf6d8b485cc1074891a197ab4225d504cb7a1ab88b02bf0" + +[[package]] +name = "winreg" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a277a57398d4bfa075df44f501a17cfdf8542d224f0d36095a2adc7aee4ef0a5" +dependencies = [ + "cfg-if", + "windows-sys 0.48.0", +] + +[[package]] +name = "zeroize" +version = "1.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ced3678a2879b30306d323f4542626697a464a97c0a07c9aebf7ebca65cd4dde" diff --git a/Cargo.toml b/Cargo.toml new file mode 100644 index 0000000..37b4c7e --- /dev/null +++ b/Cargo.toml @@ -0,0 +1,38 @@ +[package] +name = "renku-cli" +description = "A command line interface to the Renku platform" +homepage = "https://renkulab.io/" +version = "0.1.0-nightly" +edition = "2021" +license = "Apache-2.0" +repository = "https://github.com/SwissDatascienceCenter/renku-cli" +keywords = [ "renku", "cli" ] +categories = [ "command-line-utilities" ] +build = "build.rs" + +# See more keys and their definitions at +# https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +clap = { version = "4.5.7", features = ["derive", "wrap_help"] } +clap_complete = "4.5.6" +console = {version = "0.15.8"} +env_logger = { version = "0.11.3" } +log = { version = "0.4.21" } +openssl = { version = "0.10.64", optional = true } +reqwest = { version = "0.12.5", default-features = false, features = ["json", "blocking", "multipart"] } +serde = { version = "1.0.203", features = ["derive"] } +serde_json = "1.0.118" +snafu = { version = "0.8.3" } + +[features] +default = ["reqwest/default-tls"] # link against system library +rustls = ["reqwest/rustls-tls"] # include rustls, ssl library written in rust +vendored-openssl = ["openssl/vendored"] # include compiled openssl library + +[dev-dependencies] +assert_cmd = "2.0.14" +predicates = "3.1.0" + +[build-dependencies] +vergen = { version = "8.3.1", features = ["build", "git", "gitcl", "rustc", "cargo"] } diff --git a/LICENSE.txt b/LICENSE.txt new file mode 100644 index 0000000..d645695 --- /dev/null +++ b/LICENSE.txt @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/README.md b/README.md new file mode 100644 index 0000000..bb1a525 --- /dev/null +++ b/README.md @@ -0,0 +1,83 @@ +# preliminary docs + +# Goal + +- [x] outline of cli app +- [x] some tests +- [x] github ci workflows: + - [x] for publishing (what/how exactly? assume to upload a binary to + the github release page) + - [x] for testing an all platforms +- [ ] add tokio and async all the things +- [ ] nice to have: clone a project / repo + - the notion document talks about clonig a project first, then + another sentence mentions cloning repositories + - which is it? if project, how is cloning multiple repos supposed to + work? and is there anything else than `git clone` to be done? +- [ ] think better what is `pub` and what is not, thinking about + providing a rust library alongside the cli maybe +- [ ] publish musl builds with dynamically linking to openssl (perhaps + using this https://github.com/rust-cross/rust-musl-cross) +- [ ] figure how to cross compile using nix to make it better reproducible + +## Design/Outline + +- it currently is a single application crate + - it might be better to start with a multi project? + - we might want to add tooling, like creating man pages etc + - it could also be consumed as a library +- the cli uses clap as the argument parsing library, which comes + batteries-included provding a lot of convenience features out of the + box +- the main command does nothing by itself, but will always accept a sub-command +- the main accepts only a few flags that provide data common to all sub-commands +- all sub commands are write to stdout/stderr at some point, which is captured in the trait `Cmd` +- when writing the resulting values, they should implement `Sink` in + order to have a consistent output - currently json for machine + reading and "default" for humans (using the `Display` trait) +- sub commands can themselves accept sub commands (simply recursing), + the `project` command exists as an example +- serde macros are used to provide JSON de/serializer +- all commands should support two types of output: json and "human + readable", so the cli can be used in scripts and as a user +- reqwest is used to run http requests + - the module `httpclient` implements a higher level http client + adopted to renkus remote api + - currently, I opted for the synchronous variant, because: + - it results in simpler code + - right now there is no command doing lots of (io bound) + operations that would result in significant performance gain. + When we need to run many many requests/doing lots of io things, + then we should probably introduce tokio and use the async + variant of reqwest +- errors are encoded per module (currently transparent) and can be + amended with context using Snafu, creating a hierarchy +- the `assert_cmd` crate is used to provide integration tests +- the `env_log` library is used for logging, it prints to stderr by + default which is useful to provide extra information the user can + opt-in via the `-v(vv)` flags + +## Adding a new sub command + +1. Implement the command analogous to others in `src/cli/cmd/my_sub.rs` +2. Add a new variant to `SubCommand` enum in `opts.rs` +3. Follow the compile errors: + - in `cli.rs` run the command + - in `cmd.rs` add another `From` impl for the error (if necessary) + +## git + +There are the following ways to do git operations: + +- git2-rs: requires either to link to an exisitng libgit2 or include + the library in the binary + - pro: uses what git uses + - con: may involve installing a dependency with the cli, api may be + influenced by the C one +- gitoxide: a library entirely implemented in rust + - pro: looks fancy, rust api is probably nicer to work with + - con: not what git uses…, not all features supported +- use the existing git binary + - pro: smaller binary + - con: requires managing external processes (which should be easy in + rust, though), requires git as dependency diff --git a/build.rs b/build.rs new file mode 100644 index 0000000..f4ba71b --- /dev/null +++ b/build.rs @@ -0,0 +1,11 @@ +use vergen::EmitBuilder; + +pub fn main() { + EmitBuilder::builder() + .all_build() + .all_git() + .all_cargo() + .all_rustc() + .emit() + .unwrap(); +} diff --git a/deny.toml b/deny.toml new file mode 100644 index 0000000..09a4898 --- /dev/null +++ b/deny.toml @@ -0,0 +1,10 @@ +[licenses] +allow = [ + "MIT", + "Apache-2.0", + "0BSD", + "Unicode-DFS-2016" +] + +[advisories] +version = 2 \ No newline at end of file diff --git a/flake.lock b/flake.lock new file mode 100644 index 0000000..1935b82 --- /dev/null +++ b/flake.lock @@ -0,0 +1,121 @@ +{ + "nodes": { + "advisory-db": { + "flake": false, + "locked": { + "lastModified": 1718755832, + "narHash": "sha256-bSY6HPtJ9vCp0AGjL5X910aTg0mq32p3BcJmZQkNkMs=", + "owner": "rustsec", + "repo": "advisory-db", + "rev": "8eb99abe8c369b48bbd4ca04133e1f05be22a778", + "type": "github" + }, + "original": { + "owner": "rustsec", + "repo": "advisory-db", + "type": "github" + } + }, + "crane": { + "inputs": { + "nixpkgs": [ + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1718730147, + "narHash": "sha256-QmD6B6FYpuoCqu6ZuPJH896ItNquDkn0ulQlOn4ykN8=", + "owner": "ipetkov", + "repo": "crane", + "rev": "32c21c29b034d0a93fdb2379d6fabc40fc3d0e6c", + "type": "github" + }, + "original": { + "owner": "ipetkov", + "repo": "crane", + "type": "github" + } + }, + "fenix": { + "inputs": { + "nixpkgs": [ + "nixpkgs" + ], + "rust-analyzer-src": [] + }, + "locked": { + "lastModified": 1717827974, + "narHash": "sha256-ixopuTeTouxqTxfMuzs6IaRttbT8JqRW5C9Q/57WxQw=", + "owner": "nix-community", + "repo": "fenix", + "rev": "ab655c627777ab5f9964652fe23bbb1dfbd687a8", + "type": "github" + }, + "original": { + "owner": "nix-community", + "repo": "fenix", + "type": "github" + } + }, + "flake-utils": { + "inputs": { + "systems": "systems" + }, + "locked": { + "lastModified": 1710146030, + "narHash": "sha256-SZ5L6eA7HJ/nmkzGG7/ISclqe6oZdOZTNoesiInkXPQ=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "b1d9ab70662946ef0850d488da1c9019f3a9752a", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "flake-utils", + "type": "github" + } + }, + "nixpkgs": { + "locked": { + "lastModified": 1718710757, + "narHash": "sha256-zzHTI7iQByeuGDto16eRwPflCf3xfVOJJSB0/cnEd2s=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "56fc115880db6498245adecda277ccdb33025bc2", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixpkgs-unstable", + "repo": "nixpkgs", + "type": "github" + } + }, + "root": { + "inputs": { + "advisory-db": "advisory-db", + "crane": "crane", + "fenix": "fenix", + "flake-utils": "flake-utils", + "nixpkgs": "nixpkgs" + } + }, + "systems": { + "locked": { + "lastModified": 1681028828, + "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", + "owner": "nix-systems", + "repo": "default", + "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", + "type": "github" + }, + "original": { + "owner": "nix-systems", + "repo": "default", + "type": "github" + } + } + }, + "root": "root", + "version": 7 +} diff --git a/flake.nix b/flake.nix new file mode 100644 index 0000000..3c0a4c7 --- /dev/null +++ b/flake.nix @@ -0,0 +1,165 @@ +{ + description = "Build a cargo project"; + + inputs = { + nixpkgs.url = "github:NixOS/nixpkgs/nixpkgs-unstable"; + + crane = { + url = "github:ipetkov/crane"; + inputs.nixpkgs.follows = "nixpkgs"; + }; + + fenix = { + url = "github:nix-community/fenix"; + inputs.nixpkgs.follows = "nixpkgs"; + inputs.rust-analyzer-src.follows = ""; + }; + + flake-utils.url = "github:numtide/flake-utils"; + + advisory-db = { + url = "github:rustsec/advisory-db"; + flake = false; + }; + }; + + outputs = { + self, + nixpkgs, + crane, + fenix, + flake-utils, + advisory-db, + ... + }: + flake-utils.lib.eachDefaultSystem (system: let + pkgs = nixpkgs.legacyPackages.${system}; + + inherit (pkgs) lib; + + craneLib = crane.mkLib pkgs; + src = craneLib.cleanCargoSource ./.; + + # Common arguments can be set here to avoid repeating them later + commonArgs = { + inherit src; + strictDeps = true; + + nativeBuildInputs = [ + pkgs.pkg-config + ]; + buildInputs = + [ + # Add additional build inputs here + pkgs.openssl + ] + ++ lib.optionals pkgs.stdenv.isDarwin [ + # Additional darwin specific inputs can be set here + pkgs.libiconv + pkgs.darwin.apple_sdk.frameworks.Security + ]; + + # Additional environment variables can be set directly + # MY_CUSTOM_VAR = "some value"; + }; + + craneLibLLvmTools = + craneLib.overrideToolchain + (fenix.packages.${system}.complete.withComponents [ + "cargo" + "llvm-tools" + "rustc" + ]); + + # Build *just* the cargo dependencies, so we can reuse + # all of that work (e.g. via cachix) when running in CI + cargoArtifacts = craneLib.buildDepsOnly commonArgs; + + # Build the actual crate itself, reusing the dependency + # artifacts from above. + my-crate = craneLib.buildPackage (commonArgs + // { + inherit cargoArtifacts; + # additional arguments to cargo for building the app, --release is already there + cargoExtraArgs = ""; + }); + in { + checks = { + # Build the crate as part of `nix flake check` for convenience + inherit my-crate; + + # Run clippy (and deny all warnings) on the crate source, + # again, reusing the dependency artifacts from above. + # + # Note that this is done as a separate derivation so that + # we can block the CI if there are issues here, but not + # prevent downstream consumers from building our crate by itself. + my-crate-clippy = craneLib.cargoClippy (commonArgs + // { + inherit cargoArtifacts; + cargoClippyExtraArgs = "--all-targets -- --deny warnings"; + }); + + my-crate-doc = craneLib.cargoDoc (commonArgs + // { + inherit cargoArtifacts; + }); + + # Check formatting + my-crate-fmt = craneLib.cargoFmt { + inherit src; + }; + + # Audit dependencies + my-crate-audit = craneLib.cargoAudit { + inherit src advisory-db; + }; + + # Audit licenses + my-crate-deny = craneLib.cargoDeny { + inherit src; + }; + + # Run tests with cargo-nextest + # Consider setting `doCheck = false` on `my-crate` if you do not want + # the tests to run twice + my-crate-nextest = craneLib.cargoNextest (commonArgs + // { + inherit cargoArtifacts; + partitions = 1; + partitionType = "count"; + }); + }; + + packages = + { + default = my-crate; + } + // lib.optionalAttrs (!pkgs.stdenv.isDarwin) { + my-crate-llvm-coverage = craneLibLLvmTools.cargoLlvmCov (commonArgs + // { + inherit cargoArtifacts; + }); + }; + + apps.default = flake-utils.lib.mkApp { + drv = my-crate; + }; + + formatter = pkgs.alejandra; + + devShells.default = craneLib.devShell { + # Inherit inputs from checks. + checks = self.checks.${system}; + + # Additional dev-shell environment variables can be set directly + # MY_CUSTOM_DEVELOPMENT_VAR = "something else"; + RENKU_CLI_RENKU_URL = "https://ci-renku-3668.dev.renku.ch"; + + # Extra inputs can be added here; cargo and rustc are provided by default. + packages = with pkgs; [ + cargo-edit + ]; + }; + }); +} diff --git a/src/cli.rs b/src/cli.rs new file mode 100644 index 0000000..b60652d --- /dev/null +++ b/src/cli.rs @@ -0,0 +1,58 @@ +pub mod cmd; +pub mod opts; +pub mod sink; + +use self::cmd::{Cmd, CmdError, Context}; +use self::opts::{MainOpts, SubCommand}; +use clap::CommandFactory; +use serde::Serialize; +use std::fmt; + +pub fn execute_cmd(opts: MainOpts) -> Result<(), CmdError> { + let ctx = Context::new(&opts.common_opts)?; + + log::info!("Running command: {:?}", opts.subcmd); + match &opts.subcmd { + SubCommand::Version(input) => input.exec(&ctx)?, + SubCommand::ShellCompletion(input) => { + let mut app = MainOpts::command(); + input.print_completions(&mut app); + } + SubCommand::Project(input) => input.exec(&ctx)?, + }; + Ok(()) +} + +#[derive(Debug, Serialize)] +pub struct BuildInfo { + pub build_date: &'static str, + pub build_version: &'static str, + pub git_commit: &'static str, + pub rustc_host_triple: &'static str, + pub rustc_llvm_version: &'static str, + pub rustc_version: &'static str, + pub cargo_target_triple: &'static str, +} +impl Default for BuildInfo { + fn default() -> Self { + BuildInfo { + build_date: env!("VERGEN_BUILD_TIMESTAMP"), + build_version: env!("CARGO_PKG_VERSION"), + git_commit: env!("VERGEN_GIT_SHA"), + rustc_host_triple: env!("VERGEN_RUSTC_HOST_TRIPLE"), + rustc_llvm_version: env!("VERGEN_RUSTC_LLVM_VERSION"), + rustc_version: env!("VERGEN_RUSTC_SEMVER"), + cargo_target_triple: env!("VERGEN_CARGO_TARGET_TRIPLE"), + } + } +} +impl fmt::Display for BuildInfo { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + let cc = &self.git_commit[..8]; + write!( + f, + " Built at: {}\n Version: {}\n Sha: {}", + self.build_date, self.build_version, cc + ) + } +} diff --git a/src/cli/cmd.rs b/src/cli/cmd.rs new file mode 100644 index 0000000..763d2ff --- /dev/null +++ b/src/cli/cmd.rs @@ -0,0 +1,106 @@ +pub mod project; +pub mod shell_completion; +pub mod version; + +use super::sink::{Error as SinkError, Sink}; +use crate::cli::opts::{CommonOpts, Format, ProxySetting}; +use crate::httpclient::{self, proxy, Client}; +use serde::Serialize; +use snafu::{ResultExt, Snafu}; + +pub trait Cmd { + type CmdError; + + fn exec(&self, args: &Context) -> Result<(), Self::CmdError>; +} + +pub struct Context<'a> { + pub opts: &'a CommonOpts, + pub client: Client, + pub renku_url: String, +} + +const RENKULABIO: &str = "https://renkulab.io"; + +impl Context<'_> { + pub fn new(opts: &CommonOpts) -> Result { + let base_url = get_renku_url(opts); + let client = Client::new(&base_url, proxy_settings(opts), &None, false) + .context(ContextCreateSnafu)?; + Ok(Context { + opts, + client, + renku_url: base_url, + }) + } + + /// A short hand for `Sink::write(self.format(), value)` + fn write_result(&self, value: A) -> Result<(), SinkError> { + let fmt = self.format(); + Sink::write(fmt, &value) + } + + fn format(&self) -> Format { + self.opts.format.unwrap_or(Format::Default) + } +} + +fn get_renku_url(opts: &CommonOpts) -> String { + match &opts.renku_url { + Some(u) => { + log::debug!("Use renku url from arguments: {}", u); + u.clone() + } + None => match std::env::var("RENKU_CLI_RENKU_URL").ok() { + Some(u) => { + log::debug!("Use renku url from env RENKU_CLI_RENKU_URL: {}", u); + u + } + None => { + log::debug!("Use renku url: https://renkulab.io"); + RENKULABIO.to_string() + } + }, + } +} + +fn proxy_settings(opts: &CommonOpts) -> proxy::ProxySetting { + let user = opts.proxy_user.clone(); + let password = opts.proxy_password.clone(); + let prx = opts.proxy.clone(); + + log::debug!("Using proxy: {:?} @ {:?}", user, prx); + match prx { + None => proxy::ProxySetting::System, + Some(ProxySetting::None) => proxy::ProxySetting::None, + Some(ProxySetting::Custom { url }) => proxy::ProxySetting::Custom { + url: url.clone(), + user, + password, + }, + } +} + +#[derive(Debug, Snafu)] +pub enum CmdError { + #[snafu(display("ContextCreate - {}", source))] + ContextCreate { source: httpclient::Error }, + + #[snafu(display("Version - {}", source))] + Version { source: version::Error }, + + #[snafu(display("Project - {}", source))] + Project { source: project::Error }, +} + +impl From for CmdError { + fn from(source: version::Error) -> Self { + CmdError::Version { source } + } +} + +impl From for CmdError { + fn from(source: project::Error) -> Self { + CmdError::Project { source } + } +} diff --git a/src/cli/cmd/project.rs b/src/cli/cmd/project.rs new file mode 100644 index 0000000..2869fa6 --- /dev/null +++ b/src/cli/cmd/project.rs @@ -0,0 +1,33 @@ +pub mod clone; + +use super::{Cmd, Context}; +use clap::Parser; +use snafu::{ResultExt, Snafu}; + +#[derive(Debug, Snafu)] +pub enum Error { + Clone { source: clone::Error }, +} + +/// Sub command for managing projects +#[derive(Parser, Debug)] +pub struct Input { + #[command(subcommand)] + pub subcmd: ProjectCommand, +} + +impl Cmd for Input { + type CmdError = Error; + + fn exec(&self, ctx: &Context) -> Result<(), Error> { + match &self.subcmd { + ProjectCommand::Clone(input) => input.exec(ctx).context(CloneSnafu), + } + } +} + +#[derive(Parser, Debug)] +pub enum ProjectCommand { + #[command()] + Clone(clone::Input), +} diff --git a/src/cli/cmd/project/clone.rs b/src/cli/cmd/project/clone.rs new file mode 100644 index 0000000..7f94700 --- /dev/null +++ b/src/cli/cmd/project/clone.rs @@ -0,0 +1,24 @@ +use super::{Cmd, Context}; + +use clap::Parser; +use snafu::Snafu; + +/// Clone a project +#[derive(Parser, Debug)] +pub struct Input { + /// The project slug + pub slug: String, +} + +impl Cmd for Input { + type CmdError = Error; + + fn exec(&self, _ctx: &Context) -> Result<(), Error> { + Ok(()) + } +} + +#[derive(Debug, Snafu)] +pub enum Error { + Dummy, +} diff --git a/src/cli/cmd/shell_completion.rs b/src/cli/cmd/shell_completion.rs new file mode 100644 index 0000000..73f43da --- /dev/null +++ b/src/cli/cmd/shell_completion.rs @@ -0,0 +1,42 @@ +use clap::{Command, Parser, ValueEnum}; +use clap_complete::{generate, Generator, Shell}; + +/// Generates completions for some shells. +/// +#[derive(Parser, std::fmt::Debug)] +pub struct Input { + /// For which shell to generate completions. + #[arg(long, value_enum)] + pub shell: GeneratorChoice, + + /// The binary name. + #[arg(long, default_value = "renku-cli")] + pub binary: String, +} + +#[derive(ValueEnum, Clone, Debug, PartialEq)] +pub enum GeneratorChoice { + Bash, + Elvish, + Fish, + #[value(name = "powershell")] + PowerShell, + Zsh, +} + +impl Input { + pub fn print_completions(&self, app: &mut Command) { + let binary = &self.binary; + match &self.shell { + GeneratorChoice::Bash => generate_completions(Shell::Bash, binary, app), + GeneratorChoice::Elvish => generate_completions(Shell::Elvish, binary, app), + GeneratorChoice::Fish => generate_completions(Shell::Fish, binary, app), + GeneratorChoice::PowerShell => generate_completions(Shell::PowerShell, binary, app), + GeneratorChoice::Zsh => generate_completions(Shell::Zsh, binary, app), + } + } +} + +fn generate_completions(gen: G, binary: &str, app: &mut Command) { + generate(gen, app, binary, &mut std::io::stdout()); +} diff --git a/src/cli/cmd/version.rs b/src/cli/cmd/version.rs new file mode 100644 index 0000000..971c4f0 --- /dev/null +++ b/src/cli/cmd/version.rs @@ -0,0 +1,69 @@ +use super::{Cmd, Context}; +use crate::cli::sink::Error as SinkError; +use crate::cli::sink::Sink; +use crate::cli::BuildInfo; +use crate::httpclient::data::VersionInfo; +use crate::httpclient::Error as HttpError; +use clap::Parser; +use serde::Serialize; +use snafu::{ResultExt, Snafu}; +use std::fmt; + +/// Prints version about server and client. +/// +/// Queries the server for its version information and prints more +/// version details about this client. +#[derive(Parser, Debug, PartialEq)] +pub struct Input {} + +#[derive(Debug, Snafu)] +pub enum Error { + #[snafu(display("An http error occurred: {}", source))] + HttpClient { source: HttpError }, + + #[snafu(display("Error writing data: {}", source))] + WriteResult { source: SinkError }, +} + +impl Cmd for Input { + type CmdError = Error; + + fn exec(&self, ctx: &Context) -> Result<(), Error> { + let result = ctx + .client + .version(ctx.opts.verbose > 1) + .context(HttpClientSnafu)?; + let vinfo = Versions::create(result, &ctx.renku_url); + ctx.write_result(vinfo).context(WriteResultSnafu)?; + Ok(()) + } +} + +#[derive(Debug, Serialize)] +pub struct Versions<'a> { + pub client: BuildInfo, + pub server: VersionInfo, + pub renku_url: &'a str, +} +impl Versions<'_> { + pub fn create(server: VersionInfo, renku_url: &str) -> Versions { + Versions { + client: BuildInfo::default(), + server, + renku_url, + } + } +} + +impl fmt::Display for Versions<'_> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + let hc = &self.server.search.head_commit[..8]; + write!( + f, + "Client:\n{}\n\nRenku @ {}\n Data Services: {}\n Search Services: {} ({})", + self.client, self.renku_url, self.server.data.version, self.server.search.version, hc + ) + } +} + +impl Sink for Versions<'_> {} diff --git a/src/cli/opts.rs b/src/cli/opts.rs new file mode 100644 index 0000000..86206b5 --- /dev/null +++ b/src/cli/opts.rs @@ -0,0 +1,96 @@ +use super::cmd::*; +use clap::{ArgAction, ArgGroup, Parser, ValueEnum, ValueHint}; +use serde::{Deserialize, Serialize}; +use std::str::FromStr; + +/// Main options are available to all commands. They must appear +/// before a sub-command. +#[derive(Parser, Debug)] +#[command(group = ArgGroup::new("tls"))] +pub struct CommonOpts { + /// Be more verbose when logging. Verbosity increases with each + /// occurence of that option. + #[arg(short, long, action = ArgAction::Count)] + pub verbose: u8, + + /// How to format the output. The default is human readable which + /// may choose to not show every detail for better readability. + /// The json output format can be used to always show all details + /// in a structured form. + #[arg(short, long, value_enum)] + pub format: Option, + + /// The (base) URL to Renku. It can be given as environment + /// variable RENKU_CLI_RENKU_URL. + #[arg(long, value_hint = ValueHint::Url)] + pub renku_url: Option, + + /// Set a proxy to use for doing http requests. By default, the + /// system proxy will be used. Can be either `none` or . If + /// `none`, the system proxy will be ignored; otherwise specify + /// the proxy url, like `http://myproxy.com`. + #[arg(long)] + pub proxy: Option, + + /// The user to authenticate at the proxy. + #[arg(long)] + pub proxy_user: Option, + + /// The password to authenticate at the proxy. + #[arg(long)] + pub proxy_password: Option, +} + +#[derive(Parser, Debug)] +pub enum SubCommand { + #[command()] + Version(version::Input), + + #[command()] + ShellCompletion(shell_completion::Input), + + #[command()] + Project(project::Input), +} + +/// This is the command line interface to the Renku platform. Main +/// options are available to all sub-commands and must appear before +/// them. Each sub command has its own set of flags/options and +/// arguments. +#[derive(Parser, Debug)] +#[command(name = "renku-cli", version)] +pub struct MainOpts { + #[clap(flatten)] + pub common_opts: CommonOpts, + + #[clap(subcommand)] + pub subcmd: SubCommand, +} + +/// The format for presenting the results. +#[derive(ValueEnum, Debug, Copy, Clone, Serialize, Deserialize)] +pub enum Format { + Json, + Default, +} + +#[derive(Parser, Debug, Clone, Serialize, Deserialize)] +pub enum ProxySetting { + /// Don't use any proxy; this will also discard the system proxy. + None, + + /// Use a custom defined proxy. + Custom { url: String }, +} + +impl FromStr for ProxySetting { + type Err = String; + + fn from_str(s: &str) -> Result { + if s.eq_ignore_ascii_case("none") { + Ok(ProxySetting::None) + } else { + Ok(ProxySetting::Custom { url: s.to_string() }) + } + } +} diff --git a/src/cli/sink.rs b/src/cli/sink.rs new file mode 100644 index 0000000..d7369e6 --- /dev/null +++ b/src/cli/sink.rs @@ -0,0 +1,33 @@ +use crate::cli::opts::Format; +use serde::Serialize; +use snafu::Snafu; +use std::fmt::Display; + +#[derive(Debug, Snafu)] +pub enum Error { + Json { source: serde_json::Error }, +} + +pub trait Sink +where + Self: Serialize + Display, +{ + fn write(format: Format, value: &Self) -> Result<(), Error> { + match format { + Format::Json => { + serde_json::to_writer(std::io::stdout(), &value)?; + Ok(()) + } + Format::Default => { + println!("{}", &value); + Ok(()) + } + } + } +} + +impl From for Error { + fn from(e: serde_json::Error) -> Error { + Error::Json { source: e } + } +} diff --git a/src/error.rs b/src/error.rs new file mode 100644 index 0000000..a1eab22 --- /dev/null +++ b/src/error.rs @@ -0,0 +1,18 @@ +//! Global error types + +use crate::cli::cmd; +use snafu::Snafu; + +#[derive(Debug, Snafu)] +pub enum Error { + #[snafu(display("{}", source))] + Cmd { source: cmd::CmdError }, +} + +pub type Result = std::result::Result; + +impl From for Error { + fn from(e: cmd::CmdError) -> Error { + Error::Cmd { source: e } + } +} diff --git a/src/httpclient.rs b/src/httpclient.rs new file mode 100644 index 0000000..91c50e3 --- /dev/null +++ b/src/httpclient.rs @@ -0,0 +1,139 @@ +//! A http client for renku +//! +//! Provides a http client to Renku based on reqwest. +//! +//! # Usage +//! +//! ```rust +//! use renku_cli::httpclient; +//! let client = httpclient::Client::new( +//! "https://renkulab.io", +//! httpclient::proxy::ProxySetting::System, +//! &None, +//! false +//! ).unwrap(); +//! println!("{:?}", client.version(false)); +//! ``` +//! +//! # Authentication +//! +//! TODO + +pub mod data; +pub mod proxy; + +use self::data::*; +use reqwest::blocking::ClientBuilder; +use reqwest::Certificate; +use serde::de::DeserializeOwned; +use snafu::{ResultExt, Snafu}; +use std::path::PathBuf; + +const USER_AGENT: &str = concat!(env!("CARGO_PKG_NAME"), "/", env!("CARGO_PKG_VERSION")); + +#[derive(Debug, Snafu)] +pub enum Error { + #[snafu(display("An error was received from {}: {}", url, source))] + Http { source: reqwest::Error, url: String }, + + #[snafu(display("An error occurred creating the http client: {}", source))] + ClientCreate { source: reqwest::Error }, + + #[snafu(display("Error opening file '{}': {}", path.display(), source))] + OpenFile { + source: std::io::Error, + path: PathBuf, + }, + + #[snafu(display("An error occured reading the response: {}", source))] + DeserializeResp { source: reqwest::Error }, + + #[snafu(display("An error occured reading the response: {}", source))] + DeserializeJson { source: serde_json::Error }, +} + +/// The renku http client. +/// +/// This wraps a reqwest client with methods corresonding to renku api +/// endpoints. +pub struct Client { + client: reqwest::blocking::Client, + base_url: String, +} + +impl Client { + pub fn new>( + renku_url: S, + proxy: proxy::ProxySetting, + trusted_certificate: &Option, + accept_invalid_certs: bool, + ) -> Result { + let url = renku_url.into(); + log::debug!("Create renku client for: {}", url); + let mut client_builder = ClientBuilder::new().user_agent(USER_AGENT); + client_builder = proxy.set(client_builder).context(ClientCreateSnafu)?; + match trusted_certificate { + Some(cert_file) => { + log::debug!( + "Adding extra certificate from file: {}", + cert_file.display(), + ); + let buf = std::fs::read(cert_file).context(OpenFileSnafu { path: cert_file })?; + let cert = match Certificate::from_pem(&buf) { + Ok(c) => c, + Err(e) => { + log::debug!("Reading PEM format failed: {:?}. Try with DER", e); + Certificate::from_der(&buf).context(ClientCreateSnafu)? + } + }; + client_builder = client_builder.add_root_certificate(cert); + } + None => { + if accept_invalid_certs { + log::info!("NOTE: ignoring invalid certificates!"); + client_builder = client_builder.danger_accept_invalid_certs(true); + } + } + } + + let client = client_builder.build().context(ClientCreateSnafu)?; + Ok(Client { + client, + base_url: url, + }) + } + + /// Runs a GET request to the given url. When `debug` is true, the + /// response is first decoded into utf8 chars and logged at debug + /// level. Otherwise bytes are directly decoded from JSON into the + /// expected structure. + fn json_get(&self, path: &str, debug: bool) -> Result { + let url = &format!("{}{}", self.base_url, path); + if debug { + let resp = self + .client + .get(url) + .send() + .context(HttpSnafu { url })? + .text() + .context(DeserializeRespSnafu)?; + log::debug!("GET {} -> {}", url, resp); + serde_json::from_str::(&resp).context(DeserializeJsonSnafu) + } else { + self.client + .get(url) + .send() + .context(HttpSnafu { url })? + .json::() + .context(DeserializeRespSnafu) + } + } + + /// Queries Renku for its version + pub fn version(&self, debug: bool) -> Result { + let data = self.json_get::("/ui-server/api/data/version", debug)?; + let search = + self.json_get::("/ui-server/api/search/version", debug)?; + Ok(VersionInfo { search, data }) + } +} diff --git a/src/httpclient/data.rs b/src/httpclient/data.rs new file mode 100644 index 0000000..6569a74 --- /dev/null +++ b/src/httpclient/data.rs @@ -0,0 +1,24 @@ +//! Defines data structures for requests and responses and their +//! `De/Serialize` instances. + +use serde::{Deserialize, Serialize}; + +#[derive(Debug, Serialize, Deserialize)] +pub struct SearchServiceVersion { + pub name: String, + pub version: String, + #[serde(alias = "headCommit")] + pub head_commit: String, +} + +#[derive(Debug, Serialize, Deserialize)] +pub struct SimpleVersion { + pub version: String, +} + +/// Describes the version information provided by the renku platform. +#[derive(Debug, Serialize, Deserialize)] +pub struct VersionInfo { + pub search: SearchServiceVersion, + pub data: SimpleVersion, +} diff --git a/src/httpclient/proxy.rs b/src/httpclient/proxy.rs new file mode 100644 index 0000000..c5db05a --- /dev/null +++ b/src/httpclient/proxy.rs @@ -0,0 +1,40 @@ +use reqwest::blocking::ClientBuilder; +use reqwest::{Proxy, Result}; + +pub enum ProxySetting { + System, + None, + Custom { + url: String, + user: Option, + password: Option, + }, +} + +impl ProxySetting { + pub fn set(&self, builder: ClientBuilder) -> Result { + match self { + ProxySetting::System => { + log::debug!("Using system proxy (no changes to client)"); + Ok(builder) + } + ProxySetting::None => { + log::info!("Setting no_proxy"); + Ok(builder.no_proxy()) + } + ProxySetting::Custom { + url, + user, + password, + } => { + log::info!("Using proxy: {:?}", url); + let mut p = Proxy::all(url)?; + if let Some(login) = user { + log::debug!("Use proxy auth: {:?}/***", login); + p = p.basic_auth(login.as_str(), password.as_ref().unwrap_or(&"".into())); + } + Ok(builder.proxy(p)) + } + } + } +} diff --git a/src/lib.rs b/src/lib.rs new file mode 100644 index 0000000..6bfb7ad --- /dev/null +++ b/src/lib.rs @@ -0,0 +1,17 @@ +pub mod cli; +pub mod error; +pub mod httpclient; + +pub use cli::execute_cmd; + +use clap::Parser; +use cli::opts::MainOpts; + +/// Reads the program arguments into the `MainOpts` data structure. +pub fn read_args() -> MainOpts { + log::debug!("Parsing command line options…"); + let m = MainOpts::parse(); + + log::debug!("Parsed options: {:?}", m); + m +} diff --git a/src/main.rs b/src/main.rs new file mode 100644 index 0000000..ec51697 --- /dev/null +++ b/src/main.rs @@ -0,0 +1,52 @@ +use renku_cli::error::{Error, Result}; +use std::env; +use std::process; + +const LOG_LEVEL: &str = "RUST_LOG"; + +fn main() { + let error_style = console::Style::new().red().bright(); + let result = execute(); + if let Err(err) = result { + eprintln!("{}", error_style.apply_to(&err)); + process::exit(exit_code(&err)); + } +} + +fn execute() -> Result<()> { + let opts = renku_cli::read_args(); + let remove_env = match opts.common_opts.verbose { + 1 => set_log_level("info"), + n => { + if n > 1 { + set_log_level("debug") + } else { + false + } + } + }; + env_logger::init(); + + let result = renku_cli::execute_cmd(opts); + if remove_env { + env::remove_var(LOG_LEVEL); + } + result?; + Ok(()) +} + +fn set_log_level(level: &str) -> bool { + let current = env::var_os(LOG_LEVEL); + if current.is_none() { + env::set_var(LOG_LEVEL, level); + true + } else { + false + } +} + +fn exit_code(err: &Error) -> i32 { + match err { + Error::Cmd { source: _ } => 1, + } +} diff --git a/tests/common/mod.rs b/tests/common/mod.rs new file mode 100644 index 0000000..9467b0e --- /dev/null +++ b/tests/common/mod.rs @@ -0,0 +1,33 @@ +use assert_cmd::cargo::CargoError; +use assert_cmd::prelude::*; +use std::{io, process::Command}; + +#[derive(Debug)] +pub enum Error { + Cargo(CargoError), + IO(io::Error), + Json(serde_json::Error), +} +impl std::convert::From for Error { + fn from(e: CargoError) -> Self { + Error::Cargo(e) + } +} +impl std::convert::From for Error { + fn from(e: io::Error) -> Self { + Error::IO(e) + } +} +impl std::convert::From for Error { + fn from(e: serde_json::Error) -> Self { + Error::Json(e) + } +} + +pub type Result = std::result::Result; + +pub fn mk_cmd() -> Result { + let mut cmd = Command::cargo_bin("renku-cli")?; + cmd.args(["--renku-url", "https://ci-renku-3668.dev.renku.ch"]); //use mock url? + Ok(cmd) +} diff --git a/tests/version.rs b/tests/version.rs new file mode 100644 index 0000000..bc2a1a4 --- /dev/null +++ b/tests/version.rs @@ -0,0 +1,32 @@ +mod common; +use crate::common::*; +use assert_cmd::prelude::*; +use predicates::prelude::*; +use renku_cli::cli::BuildInfo; + +#[test] +#[ignore = "needs a server"] +fn version_json_cmd() -> Result<()> { + let mut cmd = mk_cmd()?; + let assert = cmd.args(["-f", "json"]).arg("version").assert(); + + let res = serde_json::from_slice::( + assert.success().stderr("").get_output().stdout.as_slice(), + )?; + assert!(res.get("client").is_some()); + assert!(res.get("server").is_some()); + assert!(res["server"].get("data").is_some()); + assert!(res["server"].get("search").is_some()); + Ok(()) +} + +#[test] +#[ignore = "needs a server"] +fn version_default_cmd() -> Result<()> { + let cmd = mk_cmd()?.arg("version").unwrap(); + let info = BuildInfo::default(); + cmd.assert() + .stderr("") + .stdout(predicate::str::is_match(format!("Version: {}", info.build_version)).unwrap()); + Ok(()) +}