├── .eslintignore ├── .eslintrc.json ├── .gitattributes ├── .github ├── dependabot.yml ├── python.json ├── release-drafter.yml └── workflows │ ├── check-dist.yml │ ├── codeql-analysis.yml │ ├── release-drafter.yml │ ├── test-cache-windows.yml │ ├── test-cache.yml │ ├── test-latest-windows.yml │ ├── test-latest.yml │ ├── test.yml │ ├── update-latest-version.yml │ └── update-major-minor-tags.yml ├── .gitignore ├── .prettierignore ├── .prettierrc.json ├── CODEOWNERS ├── LICENSE ├── README.md ├── __tests__ ├── fixtures │ ├── checksumfile │ └── rye-project │ │ ├── .python-version │ │ ├── README.md │ │ ├── pyproject.toml │ │ ├── requirements-dev.lock │ │ ├── requirements.lock │ │ └── src │ │ └── rye_project │ │ └── __init__.py ├── main.test.ts └── utils.test.ts ├── action.yml ├── dist ├── save-cache │ ├── index.js │ ├── index.js.map │ └── sourcemap-register.js ├── setup │ ├── 37.index.js │ ├── 37.index.js.map │ ├── index.js │ ├── index.js.map │ ├── licenses.txt │ └── sourcemap-register.js ├── update-checksums │ ├── index.js │ ├── index.js.map │ └── sourcemap-register.js └── update-default-version │ ├── index.js │ ├── index.js.map │ └── sourcemap-register.js ├── docs └── images │ ├── bmc-button.svg │ └── paypal-button.svg ├── jest.config.js ├── package-lock.json ├── package.json ├── src ├── checksums.ts ├── download │ ├── download-latest.ts │ └── download-version.ts ├── restore-cache.ts ├── save-cache.ts ├── setup-rye.ts ├── update-default-version.ts └── utils.ts └── tsconfig.json /.eslintignore: -------------------------------------------------------------------------------- 1 | dist/ 2 | lib/ 3 | node_modules/ 4 | jest.config.js 5 | -------------------------------------------------------------------------------- /.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "plugins": ["jest", "@typescript-eslint"], 3 | "extends": ["plugin:github/recommended"], 4 | "parser": "@typescript-eslint/parser", 5 | "parserOptions": { 6 | "ecmaVersion": 9, 7 | "sourceType": "module", 8 | "project": "./tsconfig.json" 9 | }, 10 | "rules": { 11 | "no-shadow": "off", 12 | "@typescript-eslint/no-shadow": ["error"], 13 | "i18n-text/no-en": "off", 14 | "eslint-comments/no-use": "off", 15 | "import/no-namespace": "off", 16 | "no-unused-vars": "off", 17 | "@typescript-eslint/no-unused-vars": "error", 18 | "@typescript-eslint/explicit-member-accessibility": ["error", {"accessibility": "no-public"}], 19 | "@typescript-eslint/no-require-imports": "error", 20 | "@typescript-eslint/array-type": "error", 21 | "@typescript-eslint/await-thenable": "error", 22 | "@typescript-eslint/ban-ts-comment": "error", 23 | "camelcase": "off", 24 | "@typescript-eslint/consistent-type-assertions": "error", 25 | "@typescript-eslint/explicit-function-return-type": ["error", {"allowExpressions": true}], 26 | "@typescript-eslint/func-call-spacing": ["error", "never"], 27 | "@typescript-eslint/no-array-constructor": "error", 28 | "@typescript-eslint/no-empty-interface": "error", 29 | "@typescript-eslint/no-explicit-any": "error", 30 | "@typescript-eslint/no-extraneous-class": "error", 31 | "@typescript-eslint/no-for-in-array": "error", 32 | "@typescript-eslint/no-inferrable-types": "error", 33 | "@typescript-eslint/no-misused-new": "error", 34 | "@typescript-eslint/no-namespace": "error", 35 | "@typescript-eslint/no-non-null-assertion": "warn", 36 | "@typescript-eslint/no-unnecessary-qualifier": "error", 37 | "@typescript-eslint/no-unnecessary-type-assertion": "error", 38 | "@typescript-eslint/no-useless-constructor": "error", 39 | "@typescript-eslint/no-var-requires": "error", 40 | "@typescript-eslint/prefer-for-of": "warn", 41 | "@typescript-eslint/prefer-function-type": "warn", 42 | "@typescript-eslint/prefer-includes": "error", 43 | "@typescript-eslint/prefer-string-starts-ends-with": "error", 44 | "@typescript-eslint/promise-function-async": "error", 45 | "@typescript-eslint/require-array-sort-compare": "error", 46 | "@typescript-eslint/restrict-plus-operands": "error", 47 | "semi": "off", 48 | "@typescript-eslint/semi": ["error", "never"], 49 | "@typescript-eslint/type-annotation-spacing": "error", 50 | "@typescript-eslint/unbound-method": "error" 51 | }, 52 | "env": { 53 | "node": true, 54 | "es6": true, 55 | "jest/globals": true 56 | } 57 | } -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | * text=auto eol=lf 2 | dist/** -diff linguist-generated=true -------------------------------------------------------------------------------- /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | version: 2 2 | updates: 3 | - package-ecosystem: github-actions 4 | directory: / 5 | schedule: 6 | interval: daily 7 | 8 | - package-ecosystem: npm 9 | directory: / 10 | schedule: 11 | interval: daily 12 | -------------------------------------------------------------------------------- /.github/python.json: -------------------------------------------------------------------------------- 1 | { 2 | "problemMatcher": [ 3 | { 4 | "owner": "python", 5 | "pattern": [ 6 | { 7 | "regexp": "^\\s*File\\s\\\"(.*)\\\",\\sline\\s(\\d+),\\sin\\s(.*)$", 8 | "file": 1, 9 | "line": 2 10 | }, 11 | { 12 | "regexp": "^\\s*raise\\s(.*)\\(\\'(.*)\\'\\)$", 13 | "message": 2 14 | } 15 | ] 16 | } 17 | ] 18 | } -------------------------------------------------------------------------------- /.github/release-drafter.yml: -------------------------------------------------------------------------------- 1 | name-template: 'v$RESOLVED_VERSION 🌈' 2 | tag-template: 'v$RESOLVED_VERSION' 3 | categories: 4 | - title: "🚨 Breaking changes" 5 | labels: 6 | - "breaking-change" 7 | - title: "✨ New features" 8 | labels: 9 | - "new-feature" 10 | - title: "🐛 Bug fixes" 11 | labels: 12 | - "bugfix" 13 | - title: "🚀 Enhancements" 14 | labels: 15 | - "enhancement" 16 | - "refactor" 17 | - "performance" 18 | - title: "🧰 Maintenance" 19 | labels: 20 | - "maintenance" 21 | - "ci" 22 | - title: "📚 Documentation" 23 | labels: 24 | - "documentation" 25 | - title: "⬆️ Dependency updates" 26 | labels: 27 | - "dependencies" 28 | change-template: '- $TITLE @$AUTHOR (#$NUMBER)' 29 | change-title-escapes: '\<*_&' # You can add # and @ to disable mentions, and add ` to disable code blocks. 30 | version-resolver: 31 | major: 32 | labels: 33 | - 'major' 34 | - 'breaking-change' 35 | minor: 36 | labels: 37 | - 'minor' 38 | - 'new-feature' 39 | - 'enhancement' 40 | patch: 41 | labels: 42 | - 'patch' 43 | - 'bugfix' 44 | default: patch 45 | template: | 46 | ## Changes 47 | 48 | $CHANGES -------------------------------------------------------------------------------- /.github/workflows/check-dist.yml: -------------------------------------------------------------------------------- 1 | # `dist/index.js` is a special file in Actions. 2 | # When you reference an action with `uses:` in a workflow, 3 | # `index.js` is the code that will run. 4 | # For our project, we generate this file through a build process from other source files. 5 | # We need to make sure the checked-in `index.js` actually matches what we expect it to be. 6 | name: Check dist/ 7 | 8 | on: 9 | push: 10 | branches: 11 | - main 12 | paths-ignore: 13 | - '**.md' 14 | pull_request: 15 | paths-ignore: 16 | - '**.md' 17 | workflow_dispatch: 18 | 19 | jobs: 20 | check-dist: 21 | runs-on: ubuntu-latest 22 | 23 | steps: 24 | - uses: actions/checkout@v4 25 | 26 | - name: Set up Node.js 20 27 | uses: actions/setup-node@v4 28 | with: 29 | node-version: 20 30 | 31 | - name: Install dependencies 32 | run: npm ci 33 | 34 | - name: Rebuild the dist/ directory 35 | run: | 36 | npm run build 37 | npm run package 38 | 39 | - name: Compare the expected and actual dist/ directories 40 | run: | 41 | if [ "$(git diff --ignore-space-at-eol dist/ | wc -l)" -gt "0" ]; then 42 | echo "Detected uncommitted changes after build. See status below:" 43 | git diff --text -v 44 | exit 1 45 | fi 46 | id: diff 47 | 48 | # If index.js was different than expected, upload the expected version as an artifact 49 | - uses: actions/upload-artifact@v4 50 | if: ${{ failure() && steps.diff.conclusion == 'failure' }} 51 | with: 52 | name: dist 53 | path: dist/ 54 | -------------------------------------------------------------------------------- /.github/workflows/codeql-analysis.yml: -------------------------------------------------------------------------------- 1 | # For most projects, this workflow file will not need changing; you simply need 2 | # to commit it to your repository. 3 | # 4 | # You may wish to alter this file to override the set of languages analyzed, 5 | # or to provide custom queries or build logic. 6 | # 7 | # ******** NOTE ******** 8 | # We have attempted to detect the languages in your repository. Please check 9 | # the `language` matrix defined below to confirm you have the correct set of 10 | # supported CodeQL languages. 11 | # 12 | name: "CodeQL" 13 | 14 | on: 15 | push: 16 | branches: [ main ] 17 | pull_request: 18 | # The branches below must be a subset of the branches above 19 | branches: [ main ] 20 | schedule: 21 | - cron: '31 7 * * 3' 22 | 23 | jobs: 24 | analyze: 25 | name: Analyze 26 | runs-on: ubuntu-latest 27 | permissions: 28 | actions: read 29 | contents: read 30 | security-events: write 31 | 32 | strategy: 33 | fail-fast: false 34 | matrix: 35 | language: [ 'TypeScript' ] 36 | # CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python', 'ruby' ] 37 | # Learn more about CodeQL language support at https://git.io/codeql-language-support 38 | 39 | steps: 40 | - name: Checkout repository 41 | uses: actions/checkout@v4 42 | 43 | # Initializes the CodeQL tools for scanning. 44 | - name: Initialize CodeQL 45 | uses: github/codeql-action/init@v3 46 | with: 47 | languages: ${{ matrix.language }} 48 | source-root: src 49 | # If you wish to specify custom queries, you can do so here or in a config file. 50 | # By default, queries listed here will override any specified in a config file. 51 | # Prefix the list here with "+" to use these queries and those in the config file. 52 | # queries: ./path/to/local/query, your-org/your-repo/queries@main 53 | 54 | # Autobuild attempts to build any compiled languages (C/C++, C#, or Java). 55 | # If this step fails, then you should remove it and run the build manually (see below) 56 | - name: Autobuild 57 | uses: github/codeql-action/autobuild@v3 58 | 59 | # ℹ️ Command-line programs to run using the OS shell. 60 | # 📚 https://git.io/JvXDl 61 | 62 | # ✏️ If the Autobuild fails above, remove it and uncomment the following three lines 63 | # and modify them (or add more) to build your code if your project 64 | # uses a compiled language 65 | 66 | #- run: | 67 | # make bootstrap 68 | # make release 69 | 70 | - name: Perform CodeQL Analysis 71 | uses: github/codeql-action/analyze@v3 72 | -------------------------------------------------------------------------------- /.github/workflows/release-drafter.yml: -------------------------------------------------------------------------------- 1 | --- 2 | name: Release Drafter 3 | 4 | # yamllint disable-line rule:truthy 5 | on: 6 | push: 7 | branches: 8 | - main 9 | workflow_dispatch: 10 | 11 | jobs: 12 | update_release_draft: 13 | name: ✏️ Draft release 14 | runs-on: ubuntu-latest 15 | steps: 16 | - name: 🚀 Run Release Drafter 17 | uses: release-drafter/release-drafter@v6.0.0 18 | env: 19 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} -------------------------------------------------------------------------------- /.github/workflows/test-cache-windows.yml: -------------------------------------------------------------------------------- 1 | name: 'test-cache-windows' 2 | on: 3 | pull_request: 4 | push: 5 | branches: 6 | - main 7 | 8 | concurrency: 9 | group: ${{ github.workflow }}-${{ github.ref }} 10 | cancel-in-progress: true 11 | 12 | jobs: 13 | test-setup-cache: 14 | runs-on: ${{ matrix.os }} 15 | strategy: 16 | matrix: 17 | os: [windows-latest] 18 | steps: 19 | - uses: actions/checkout@v4 20 | - name: Setup with cache 21 | uses: ./ 22 | with: 23 | enable-cache: true 24 | working-directory: __tests__\fixtures\rye-project 25 | cache-prefix: ${{ github.run_id }}-${{ github.run_attempt }} 26 | - run: rye sync 27 | working-directory: __tests__\fixtures\rye-project 28 | test-restore-cache: 29 | runs-on: ${{ matrix.os }} 30 | strategy: 31 | matrix: 32 | os: [windows-latest] 33 | needs: test-setup-cache 34 | steps: 35 | - uses: actions/checkout@v4 36 | - name: Restore with cache 37 | id: restore 38 | uses: ./ 39 | with: 40 | enable-cache: true 41 | working-directory: __tests__\fixtures\rye-project 42 | cache-prefix: ${{ github.run_id }}-${{ github.run_attempt }} 43 | - name: Cache was hit 44 | run: | 45 | if ($env:CACHE_HIT -ne "true") { 46 | exit 1 47 | } 48 | env: 49 | CACHE_HIT: ${{ steps.restore.outputs.cache-hit }} 50 | - run: rye sync 51 | working-directory: __tests__\fixtures\rye-project 52 | -------------------------------------------------------------------------------- /.github/workflows/test-cache.yml: -------------------------------------------------------------------------------- 1 | name: 'test-cache' 2 | on: 3 | pull_request: 4 | push: 5 | branches: 6 | - main 7 | 8 | concurrency: 9 | group: ${{ github.workflow }}-${{ github.ref }} 10 | cancel-in-progress: true 11 | 12 | jobs: 13 | test-setup-cache: 14 | runs-on: ${{ matrix.os }} 15 | strategy: 16 | matrix: 17 | os: [ubuntu-latest, macos-latest, macos-14] 18 | steps: 19 | - uses: actions/checkout@v4 20 | - name: Setup with cache 21 | uses: ./ 22 | with: 23 | enable-cache: true 24 | working-directory: __tests__/fixtures/rye-project 25 | cache-prefix: ${{ github.run_id }}-${{ github.run_attempt }} 26 | - run: rye sync 27 | working-directory: __tests__/fixtures/rye-project 28 | test-restore-cache: 29 | runs-on: ${{ matrix.os }} 30 | strategy: 31 | matrix: 32 | os: [ubuntu-latest, macos-latest, macos-14] 33 | needs: test-setup-cache 34 | steps: 35 | - uses: actions/checkout@v4 36 | - name: Restore with cache 37 | id: restore 38 | uses: ./ 39 | with: 40 | enable-cache: true 41 | working-directory: __tests__/fixtures/rye-project 42 | cache-prefix: ${{ github.run_id }}-${{ github.run_attempt }} 43 | - name: Cache was hit 44 | run: | 45 | if [ "$CACHE_HIT" != "true" ]; then 46 | exit 1 47 | fi 48 | env: 49 | CACHE_HIT: ${{ steps.restore.outputs.cache-hit }} 50 | - run: rye sync 51 | working-directory: __tests__/fixtures/rye-project 52 | 53 | test-setup-cache-local: 54 | runs-on: oracle-aarch64 55 | steps: 56 | - uses: actions/checkout@v4 57 | - name: Setup with cache 58 | uses: ./ 59 | with: 60 | enable-cache: true 61 | working-directory: __tests__/fixtures/rye-project 62 | cache-prefix: ${{ github.run_id }}-${{ github.run_attempt }} 63 | cache-local-storage-path: /tmp/rye-cache 64 | - run: rye sync 65 | working-directory: __tests__/fixtures/rye-project 66 | test-restore-cache-local: 67 | runs-on: oracle-aarch64 68 | needs: test-setup-cache-local 69 | steps: 70 | - uses: actions/checkout@v4 71 | - name: Restore with cache 72 | id: restore 73 | uses: ./ 74 | with: 75 | enable-cache: true 76 | working-directory: __tests__/fixtures/rye-project 77 | cache-prefix: ${{ github.run_id }}-${{ github.run_attempt }} 78 | cache-local-storage-path: /tmp/rye-cache 79 | - name: Cache was hit 80 | run: | 81 | if [ "$CACHE_HIT" != "true" ]; then 82 | exit 1 83 | fi 84 | env: 85 | CACHE_HIT: ${{ steps.restore.outputs.cache-hit }} 86 | - run: rye sync 87 | working-directory: __tests__/fixtures/rye-project 88 | 89 | test-setup-cache-local-venv-path-mismatch: 90 | runs-on: oracle-aarch64 91 | steps: 92 | - uses: actions/checkout@v4 93 | - name: Setup with cache 94 | uses: ./ 95 | with: 96 | enable-cache: true 97 | working-directory: __tests__/fixtures/rye-project 98 | cache-prefix: ${{ github.run_id }}-${{ github.run_attempt }}-path-mismatch 99 | cache-local-storage-path: /tmp/rye-cache 100 | - run: rye sync 101 | working-directory: __tests__/fixtures/rye-project 102 | alter-venv-path-in-cache-local: 103 | runs-on: oracle-aarch64 104 | needs: test-setup-cache-local 105 | steps: 106 | - uses: actions/checkout@v4 107 | - name: Alter venv path in cache 108 | run: | 109 | RYE_VENV_PATH=$(find /tmp/rye-cache -type f -name 'rye-venv.json' -path '/tmp/rye-cache/${{ github.run_id }}-${{ github.run_attempt }}-path-mismatch*') 110 | sed -i 's/"venv_path":\s*"[^"]*"/"venv_path": "something"/' "$RYE_VENV_PATH" 111 | test-restore-cache-local-venv-path-mismatch: 112 | runs-on: oracle-aarch64 113 | needs: alter-venv-path-in-cache-local 114 | steps: 115 | - uses: actions/checkout@v4 116 | - name: Restore with cache 117 | id: restore 118 | uses: ./ 119 | with: 120 | enable-cache: true 121 | working-directory: __tests__/fixtures/rye-project 122 | cache-prefix: ${{ github.run_id }}-${{ github.run_attempt }}-path-mismatch 123 | cache-local-storage-path: /tmp/rye-cache 124 | - name: Cache was not hit 125 | run: | 126 | if [ "$CACHE_HIT" == "true" ]; then 127 | exit 1 128 | fi 129 | env: 130 | CACHE_HIT: ${{ steps.restore.outputs.cache-hit }} 131 | - run: rye sync 132 | working-directory: __tests__/fixtures/rye-project -------------------------------------------------------------------------------- /.github/workflows/test-latest-windows.yml: -------------------------------------------------------------------------------- 1 | name: 'test-latest-windows' 2 | on: 3 | pull_request: 4 | push: 5 | branches: 6 | - main 7 | 8 | concurrency: 9 | group: ${{ github.workflow }}-${{ github.ref }} 10 | cancel-in-progress: true 11 | 12 | jobs: 13 | test-latest: 14 | runs-on: windows-latest 15 | steps: 16 | - uses: actions/checkout@v4 17 | - name: Should not be on path 18 | run: | 19 | if (!(Get-Command -Name "rye" -ErrorAction SilentlyContinue)) { 20 | exit 0 21 | } else { 22 | exit 1 23 | } 24 | - name: Setup rye 25 | uses: ./ 26 | with: 27 | version: latest 28 | working-directory: __tests__\fixtures\rye-project 29 | github-token: ${{ secrets.GITHUB_TOKEN }} 30 | - run: rye sync 31 | working-directory: __tests__\fixtures\rye-project 32 | - name: Rye path is not added to .profile 33 | run: | 34 | $env:Path -split ';' | ForEach-Object { 35 | if ($_ -eq "C:\path\to\rye") { 36 | exit 1 37 | } 38 | } 39 | exit 0 40 | test-latest-without-github-token: 41 | runs-on: windows-latest 42 | steps: 43 | - uses: actions/checkout@v4 44 | - name: Setup rye 45 | uses: ./ 46 | with: 47 | version: latest 48 | - run: rye sync 49 | working-directory: __tests__\fixtures\rye-project 50 | -------------------------------------------------------------------------------- /.github/workflows/test-latest.yml: -------------------------------------------------------------------------------- 1 | name: 'test-latest' 2 | on: 3 | pull_request: 4 | push: 5 | branches: 6 | - main 7 | 8 | concurrency: 9 | group: ${{ github.workflow }}-${{ github.ref }} 10 | cancel-in-progress: true 11 | 12 | jobs: 13 | test-latest: 14 | runs-on: ${{ matrix.os }} 15 | strategy: 16 | matrix: 17 | os: [ubuntu-latest, macos-latest, macos-14, oracle-aarch64] 18 | enable-cache: [true, false] 19 | steps: 20 | - uses: actions/checkout@v4 21 | - name: Should not be on path 22 | run: | 23 | if ! which rye; 24 | then 25 | exit 0 26 | else 27 | exit 1 28 | fi 29 | - name: Setup rye 30 | uses: ./ 31 | with: 32 | version: latest 33 | working-directory: __tests__/fixtures/rye-project 34 | github-token: ${{ secrets.GITHUB_TOKEN }} 35 | enable-cache: ${{ matrix.enable-cache }} 36 | - run: rye sync 37 | working-directory: __tests__/fixtures/rye-project 38 | - name: Rye path is not added to .profile 39 | run: | 40 | if ! grep -q "rye" ~/.profile; 41 | then 42 | exit 0 43 | else 44 | exit 1 45 | fi 46 | test-latest-without-github-token: 47 | runs-on: ubuntu-latest 48 | steps: 49 | - uses: actions/checkout@v4 50 | - name: Setup rye 51 | uses: ./ 52 | with: 53 | version: latest 54 | - run: rye sync 55 | working-directory: __tests__/fixtures/rye-project 56 | 57 | test-latest-automatic-toolchain: 58 | runs-on: ${{ matrix.os }} 59 | strategy: 60 | matrix: 61 | os: [ubuntu-latest, macos-latest, macos-14, oracle-aarch64] 62 | steps: 63 | - uses: actions/checkout@v4 64 | - name: Determine expected python version 65 | id: determine-expected-python-version 66 | run: | 67 | EXPECTED_PYTHON_VERSION=$(cat .python-version) 68 | echo "EXPECTED_PYTHON_VERSION=$EXPECTED_PYTHON_VERSION" >> "$GITHUB_OUTPUT" 69 | working-directory: __tests__/fixtures/rye-project 70 | - name: Setup rye 71 | uses: ./ 72 | with: 73 | version: latest 74 | working-directory: __tests__/fixtures/rye-project 75 | - run: rye sync 76 | working-directory: __tests__/fixtures/rye-project 77 | - name: Check python version 78 | run: | 79 | ACTUAL_PYTHON_VERSION=$(ls $RYE_HOME/py) 80 | if [ "$ACTUAL_PYTHON_VERSION" != "$EXPECTED_PYTHON_VERSION" ]; 81 | then 82 | echo "$ACTUAL_PYTHON_VERSION is not the same as $EXPECTED_PYTHON_VERSION" 83 | exit 1 84 | fi 85 | env: 86 | EXPECTED_PYTHON_VERSION: ${{ steps.determine-expected-python-version.outputs.EXPECTED_PYTHON_VERSION }} 87 | -------------------------------------------------------------------------------- /.github/workflows/test.yml: -------------------------------------------------------------------------------- 1 | name: 'test' 2 | on: 3 | pull_request: 4 | push: 5 | branches: 6 | - main 7 | 8 | concurrency: 9 | group: ${{ github.workflow }}-${{ github.ref }} 10 | cancel-in-progress: true 11 | 12 | jobs: 13 | build: 14 | runs-on: ${{ matrix.os }} 15 | strategy: 16 | matrix: 17 | os: [ubuntu-latest, macos-latest, macos-14, oracle-aarch64] 18 | steps: 19 | - uses: actions/checkout@v4 20 | - uses: actions/setup-node@v4 21 | with: 22 | node-version: '20' 23 | - run: | 24 | npm install 25 | - run: | 26 | npm run all 27 | test-default-version: 28 | runs-on: ${{ matrix.os }} 29 | strategy: 30 | matrix: 31 | os: [ubuntu-latest, oracle-aarch64] 32 | steps: 33 | - uses: actions/checkout@v4 34 | - name: Install default version 35 | uses: ./ 36 | with: 37 | github-token: ${{ secrets.GITHUB_TOKEN }} 38 | - run: | 39 | which rye 40 | test-specific-version: 41 | runs-on: ${{ matrix.os }} 42 | strategy: 43 | matrix: 44 | os: [ubuntu-latest, oracle-aarch64] 45 | rye-version: ['0.3.0','0.4.0'] 46 | steps: 47 | - uses: actions/checkout@v4 48 | - name: Install version ${{ matrix.rye-version }} 49 | uses: ./ 50 | with: 51 | version: ${{ matrix.rye-version }} 52 | github-token: ${{ secrets.GITHUB_TOKEN }} 53 | - run: | 54 | which rye 55 | test-checksum: 56 | runs-on: ${{ matrix.os }} 57 | strategy: 58 | matrix: 59 | os: [ubuntu-latest, oracle-aarch64] 60 | checksum: ['00e795573477a2fe2b3c0ac748240364c3369218d314d1df47d2653764e9bfb1'] 61 | exclude: 62 | - os: oracle-aarch64 63 | checksum: '00e795573477a2fe2b3c0ac748240364c3369218d314d1df47d2653764e9bfb1' 64 | include: 65 | - os: oracle-aarch64 66 | checksum: '7e0b1f6e3490a79c1d2600e8c04dd9ed4ea04d29d6c80f1f5a84a79736e9a21d' 67 | steps: 68 | - uses: actions/checkout@v4 69 | - name: Checksum matches expected 70 | uses: ./ 71 | with: 72 | version: '0.11.0' 73 | checksum: ${{ matrix.checksum }} 74 | github-token: ${{ secrets.GITHUB_TOKEN }} 75 | test-modify-path-warning: 76 | runs-on: ubuntu-latest 77 | steps: 78 | - uses: actions/checkout@v4 79 | - name: Install version which modifies path 80 | uses: ./ 81 | with: 82 | version: '0.21.0' 83 | github-token: ${{ secrets.GITHUB_TOKEN }} 84 | - run: which rye 85 | - name: Rye path is added to .profile 86 | run: | 87 | if grep -q "rye" ~/.profile; 88 | then 89 | exit 0 90 | else 91 | exit 1 92 | fi 93 | -------------------------------------------------------------------------------- /.github/workflows/update-latest-version.yml: -------------------------------------------------------------------------------- 1 | name: 'Update Checksums' 2 | on: 3 | workflow_dispatch: 4 | schedule: 5 | - cron: "0 0 * * *" 6 | 7 | jobs: 8 | build: 9 | runs-on: ubuntu-latest 10 | steps: 11 | - uses: actions/checkout@v4 12 | - uses: actions/setup-node@v4 13 | with: 14 | node-version: '20' 15 | - name: Update default version and checksums 16 | id: update-default-version 17 | run: node dist/update-default-version/index.js src/checksums.ts action.yml ${{ secrets.GITHUB_TOKEN }} 18 | - run: npm install && npm run all 19 | - name: Create Pull Request 20 | uses: peter-evans/create-pull-request@5e914681df9dc83aa4e4905692ca88beb2f9e91f # v7.0.5 21 | with: 22 | commit-message: "chore: update checksums" 23 | title: "chore: update default version to ${{ steps.update-default-version.outputs.latest-version }}" 24 | body: "chore: update default version to ${{ steps.update-default-version.outputs.latest-version }}" 25 | base: main 26 | labels: "automated-pr,bugfix" 27 | branch: update-default-version-pr 28 | delete-branch: true -------------------------------------------------------------------------------- /.github/workflows/update-major-minor-tags.yml: -------------------------------------------------------------------------------- 1 | --- 2 | name: Update Major Minor Tags 3 | 4 | # yamllint disable-line rule:truthy 5 | on: 6 | push: 7 | branches-ignore: 8 | - '**' 9 | tags: 10 | - 'v*.*.*' 11 | 12 | jobs: 13 | update_major_minor_tags: 14 | name: Make sure major and minor tags are up to date on a patch release 15 | runs-on: ubuntu-latest 16 | steps: 17 | - uses: actions/checkout@v4 18 | - name: Run Update semver 19 | uses: haya14busa/action-update-semver@v1.2.1 -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Dependency directory 2 | node_modules 3 | 4 | # Rest pulled from https://github.com/github/gitignore/blob/master/Node.gitignore 5 | # Logs 6 | logs 7 | *.log 8 | npm-debug.log* 9 | yarn-debug.log* 10 | yarn-error.log* 11 | lerna-debug.log* 12 | 13 | # Diagnostic reports (https://nodejs.org/api/report.html) 14 | report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json 15 | 16 | # Runtime data 17 | pids 18 | *.pid 19 | *.seed 20 | *.pid.lock 21 | 22 | # Directory for instrumented libs generated by jscoverage/JSCover 23 | lib-cov 24 | 25 | # Coverage directory used by tools like istanbul 26 | coverage 27 | *.lcov 28 | 29 | # nyc test coverage 30 | .nyc_output 31 | 32 | # Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files) 33 | .grunt 34 | 35 | # Bower dependency directory (https://bower.io/) 36 | bower_components 37 | 38 | # node-waf configuration 39 | .lock-wscript 40 | 41 | # Compiled binary addons (https://nodejs.org/api/addons.html) 42 | build/Release 43 | 44 | # Dependency directories 45 | jspm_packages/ 46 | 47 | # TypeScript v1 declaration files 48 | typings/ 49 | 50 | # TypeScript cache 51 | *.tsbuildinfo 52 | 53 | # Optional npm cache directory 54 | .npm 55 | 56 | # Optional eslint cache 57 | .eslintcache 58 | 59 | # Optional REPL history 60 | .node_repl_history 61 | 62 | # Output of 'npm pack' 63 | *.tgz 64 | 65 | # Yarn Integrity file 66 | .yarn-integrity 67 | 68 | # dotenv environment variables file 69 | .env 70 | .env.test 71 | 72 | # parcel-bundler cache (https://parceljs.org/) 73 | .cache 74 | 75 | # next.js build output 76 | .next 77 | 78 | # nuxt.js build output 79 | .nuxt 80 | 81 | # vuepress build output 82 | .vuepress/dist 83 | 84 | # Serverless directories 85 | .serverless/ 86 | 87 | # FuseBox cache 88 | .fusebox/ 89 | 90 | # DynamoDB Local files 91 | .dynamodb/ 92 | 93 | # OS metadata 94 | .DS_Store 95 | Thumbs.db 96 | 97 | # Ignore built ts files 98 | __tests__/runner/* 99 | lib/**/* -------------------------------------------------------------------------------- /.prettierignore: -------------------------------------------------------------------------------- 1 | dist/ 2 | lib/ 3 | node_modules/ -------------------------------------------------------------------------------- /.prettierrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "printWidth": 80, 3 | "tabWidth": 2, 4 | "useTabs": false, 5 | "semi": false, 6 | "singleQuote": true, 7 | "trailingComma": "none", 8 | "bracketSpacing": false, 9 | "arrowParens": "avoid" 10 | } 11 | -------------------------------------------------------------------------------- /CODEOWNERS: -------------------------------------------------------------------------------- 1 | * @eifinger 2 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2023 Kevin Stillhammer 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # setup-rye 2 | 3 | Set up your GitHub Actions workflow with a specific version of [rye](https://rye-up.com/). 4 | 5 | * Install a version of rye and add it to the path 6 | * Cache the installed version of rye to speed up consecutive runs on self-hosted runners 7 | * Register problem matchers for error output 8 | * Optional: Cache the virtual environment created by rye 9 | * Optional: Verify the checksum of the downloaded rye executable 10 | 11 | > [!TIP] 12 | > Want to switch to [uv](https://docs.astral.sh/uv)? Check out [astral-sh/setup-uv](https://github.com/astral-sh/setup-uv) 13 | 14 | ## Usage 15 | 16 | Example workflow can be found [in this repo](https://github.com/eifinger/pywaze/blob/main/.github/workflows/ci.yml) 17 | 18 | ```yaml 19 | - name: Install the latest version of rye 20 | uses: eifinger/setup-rye@v4 21 | ``` 22 | 23 | ### Install latest version 24 | 25 | By default this action installs the version defined as `default` in `action.yml`. 26 | This gets automatically updated in a new release of this action when a new version of rye is released. 27 | If you don't want to wait for a new release of this action you can use use `version: latest`. 28 | 29 | > [!WARNING] 30 | > Using the `latest` version means that the rye executable gets downloaded every single time instead of loaded from the tools cache. 31 | > This can take up to 20s depending on the download speed. 32 | > This does not affect the cached version of `.venv` when caching is enabled. 33 | 34 | ```yaml 35 | - name: Install a specific version 36 | uses: eifinger/setup-rye@v4 37 | with: 38 | version: 'latest' 39 | ``` 40 | 41 | ### Install specific version 42 | 43 | You can also specify a specific version of rye 44 | 45 | ```yaml 46 | - name: Install a specific version 47 | uses: eifinger/setup-rye@v4 48 | with: 49 | version: '0.12.0' 50 | ``` 51 | 52 | ### Validate checksum 53 | 54 | You can also specify a checksum to validate the downloaded file. 55 | Checksums of versions 0.12.0 and later are automatically verified by this action. 56 | The sha265 hashes can be found on the [releases page](https://github.com/astral-sh/rye/releases) 57 | of the rye repo. 58 | 59 | ```yaml 60 | - name: Install a specific version and validate the checksum 61 | uses: eifinger/setup-rye@v4 62 | with: 63 | version: '0.12.0' 64 | checksum: 'c48d850e90649d868d512f60af67c74aa844d80f951fdb38589220662e709da7' 65 | ``` 66 | 67 | ### Enable caching 68 | 69 | If you enable caching the virtual environment which gets created by `rye` under `.venv` will 70 | be cached. This can speed up runs which can reuse the cache 71 | by several minutes. 72 | 73 | You can optionally define a custom cache key prefix. 74 | 75 | ```yaml 76 | - name: Enable caching and define a custom cache key prefix 77 | id: setup-rye 78 | uses: eifinger/setup-rye@v4 79 | with: 80 | enable-cache: true 81 | cache-prefix: 'optional-prefix' 82 | ``` 83 | 84 | When the cache was successfully restored the output `cache-hit` will be set to `true` and you can use it in subsequent steps. 85 | For the example above you can use it like this: 86 | 87 | ```yaml 88 | - name: Do something if the cache was restored 89 | if: steps.setup-rye.outputs.cache-hit == 'true' 90 | run: echo "Cache was restored" 91 | ``` 92 | 93 | #### Working directory 94 | 95 | If your rye project is not at the root of the repository you can specify the working directory 96 | relative to the repository root. This is useful for monorepos. 97 | 98 | ```yaml 99 | - name: Enable caching and define a working directory 100 | uses: eifinger/setup-rye@v4 101 | with: 102 | enable-cache: true 103 | working-directory: 'path/to/rye/project' 104 | ``` 105 | 106 | #### Local storage path 107 | 108 | If you want to save the cache to a local path you can specify the path with the `cache-local-storage-path` input. 109 | This can be useful if you are on a self hosted runner and want to save time and network traffic. 110 | 111 | ```yaml 112 | - name: Enable caching and define a custom cache path 113 | uses: eifinger/setup-rye@v4 114 | with: 115 | enable-cache: true 116 | cache-local-storage-path: '/path/to/cache' 117 | ``` 118 | 119 | It is recommended to cleanup the storage path to avoid running out of disk space. 120 | One option is to use a cron job to delete files older than 7 days like below. 121 | 122 | ```yaml 123 | 0 0 * * * find /home/ubuntu/setup-rye-cache -type d -mtime +7 -exec rm -rf {} \; 124 | ``` 125 | 126 | ### API rate limit 127 | 128 | To avoid hitting the error `API rate limit exceeded` you can supply a GitHub token with the `github-token` input. 129 | 130 | ```yaml 131 | - name: Install rye and supply a GitHub token 132 | uses: eifinger/setup-rye@v4 133 | with: 134 | github-token: ${{ secrets.GITHUB_TOKEN }} 135 | ``` 136 | 137 | ## How it works 138 | 139 | This action downloads rye from the releases of the [rye repo](https://github.com/astral-sh/rye) and uses the [GitHub Actions Toolkit](https://github.com/actions/toolkit) to cache it as a tool to speed up consecutive runs especially on self-hosted runners. 140 | 141 | The installed version of rye is then added to the runner path so other steps can just use it by calling `rye`. 142 | To prevent interfering the other rye processes on the same runner `RYE_HOME` gets set to the repository roots parent and is cleaned up after a workflow run. 143 | 144 | ## FAQ 145 | 146 | ### Do I still need actions/setup-python when using this action? 147 | 148 | No! This action was modelled as a drop-in replacement for `actions/setup-python` when using rye. 149 | 150 | A simple example workflow could look like this: 151 | 152 | ```yaml 153 | - name: Checkout the repository 154 | uses: actions/checkout@v2 155 | - name: Install the latest version of rye 156 | uses: eifinger/setup-rye@v4 157 | with: 158 | enable-cache: true 159 | - name: Sync dependencies 160 | run: rye sync 161 | - name: Lint 162 | run: rye lint 163 | ``` 164 | 165 | --- 166 | 167 | [](https://www.buymeacoffee.com/eifinger) 168 | [](https://paypal.me/kevinstillhammer) 169 | -------------------------------------------------------------------------------- /__tests__/fixtures/checksumfile: -------------------------------------------------------------------------------- 1 | Random file content -------------------------------------------------------------------------------- /__tests__/fixtures/rye-project/.python-version: -------------------------------------------------------------------------------- 1 | cpython@3.11.3 2 | -------------------------------------------------------------------------------- /__tests__/fixtures/rye-project/README.md: -------------------------------------------------------------------------------- 1 | # rye-project 2 | 3 | Describe your project here. 4 | -------------------------------------------------------------------------------- /__tests__/fixtures/rye-project/pyproject.toml: -------------------------------------------------------------------------------- 1 | [project] 2 | name = "rye-project" 3 | version = "0.1.0" 4 | description = "Add your description here" 5 | authors = [ 6 | { name = "Kevin Stillhammer", email = "kevin.stillhammer@gmail.com" } 7 | ] 8 | dependencies = [ 9 | "black>=23.7.0", 10 | ] 11 | readme = "README.md" 12 | requires-python = ">= 3.8" 13 | 14 | [build-system] 15 | requires = ["hatchling"] 16 | build-backend = "hatchling.build" 17 | 18 | [tool.rye] 19 | managed = true 20 | dev-dependencies = [] 21 | 22 | [tool.hatch.metadata] 23 | allow-direct-references = true 24 | -------------------------------------------------------------------------------- /__tests__/fixtures/rye-project/requirements-dev.lock: -------------------------------------------------------------------------------- 1 | # generated by rye 2 | # use `rye lock` or `rye sync` to update this lockfile 3 | # 4 | # last locked with the following flags: 5 | # pre: false 6 | # features: [] 7 | # all-features: false 8 | 9 | -e file:. 10 | black==23.7.0 11 | click==8.1.6 12 | mypy-extensions==1.0.0 13 | packaging==23.1 14 | pathspec==0.11.2 15 | platformdirs==3.10.0 16 | -------------------------------------------------------------------------------- /__tests__/fixtures/rye-project/requirements.lock: -------------------------------------------------------------------------------- 1 | # generated by rye 2 | # use `rye lock` or `rye sync` to update this lockfile 3 | # 4 | # last locked with the following flags: 5 | # pre: false 6 | # features: [] 7 | # all-features: false 8 | 9 | -e file:. 10 | black==23.7.0 11 | click==8.1.6 12 | mypy-extensions==1.0.0 13 | packaging==23.1 14 | pathspec==0.11.2 15 | platformdirs==3.10.0 16 | -------------------------------------------------------------------------------- /__tests__/fixtures/rye-project/src/rye_project/__init__.py: -------------------------------------------------------------------------------- 1 | def hello(): 2 | return "Hello from rye-project!" 3 | -------------------------------------------------------------------------------- /__tests__/main.test.ts: -------------------------------------------------------------------------------- 1 | import {expect, test} from '@jest/globals' 2 | 3 | test('todo', async () => { 4 | const todo = 'todo' 5 | expect(todo).toBe('todo') 6 | }) 7 | -------------------------------------------------------------------------------- /__tests__/utils.test.ts: -------------------------------------------------------------------------------- 1 | import {expect, test, it} from '@jest/globals' 2 | 3 | import * as utils from '../src/utils' 4 | 5 | test('checksum should match', async () => { 6 | const validChecksum = 7 | 'f3da96ec7e995debee7f5d52ecd034dfb7074309a1da42f76429ecb814d813a3' 8 | const filePath = '__tests__/fixtures/checksumfile' 9 | const isValid = await utils.validateFileCheckSum(filePath, validChecksum) 10 | expect(isValid).toBeTruthy() 11 | }) 12 | 13 | type KnownVersionFixture = {version: string; known: boolean} 14 | 15 | it.each([ 16 | { 17 | version: '0.12.0', 18 | known: true 19 | }, 20 | { 21 | version: '0.4.0', 22 | known: true 23 | }, 24 | { 25 | version: '0.3.0', 26 | known: false 27 | } 28 | ])( 29 | 'isknownVersion should return $known for version $version', 30 | ({version, known}) => { 31 | expect(utils.isknownVersion(version)).toBe(known) 32 | } 33 | ) 34 | 35 | type VersionComparisonFixture = { 36 | versionA: string 37 | is: utils.ComparisonResult 38 | versionB: string 39 | } 40 | 41 | it.each([ 42 | { 43 | versionA: '0.12.0', 44 | is: utils.ComparisonResult.Equal, 45 | versionB: '0.12.0' 46 | }, 47 | { 48 | versionA: '0.12.0', 49 | is: utils.ComparisonResult.Less, 50 | versionB: '0.12.1' 51 | }, 52 | { 53 | versionA: '0.12.0', 54 | is: utils.ComparisonResult.Less, 55 | versionB: '0.13.0' 56 | }, 57 | { 58 | versionA: '0.12.1', 59 | is: utils.ComparisonResult.Greater, 60 | versionB: '0.12.0' 61 | }, 62 | { 63 | versionA: '0.13.0', 64 | is: utils.ComparisonResult.Greater, 65 | versionB: '0.12.0' 66 | }, 67 | { 68 | versionA: '1.0.0', 69 | is: utils.ComparisonResult.Greater, 70 | versionB: '0.12.0' 71 | } 72 | ])('$versionA should be $is to $versionB', ({versionA, is, versionB}) => { 73 | expect(utils.compareVersions(versionA, versionB)).toBe(is) 74 | }) 75 | -------------------------------------------------------------------------------- /action.yml: -------------------------------------------------------------------------------- 1 | name: 'Python Setup Rye' 2 | description: 'Set up and cache rye and add it to the PATH' 3 | author: 'eifinger' 4 | inputs: 5 | version: 6 | description: 'The version of rye to install' 7 | default: '0.44.0' 8 | checksum: 9 | description: 'The checksum of the rye version to install' 10 | required: false 11 | github-token: 12 | description: 'Used to increase the rate limit when retrieving versions and downloading rye.' 13 | required: false 14 | enable-cache: 15 | description: 'Enable caching of .venv' 16 | default: 'false' 17 | working-directory: 18 | description: 'The location of the rye project relative to the root of the repository' 19 | required: false 20 | cache-prefix: 21 | description: 'Prefix for the cache key' 22 | required: false 23 | cache-local-storage-path: 24 | description: 'Local path to store the cache. Will be used instead of the GitHub Actions cache' 25 | required: false 26 | outputs: 27 | rye-version: 28 | description: "The installed rye version. Useful when using latest." 29 | cache-hit: 30 | description: "A boolean value to indicate a cache entry was found" 31 | runs: 32 | using: 'node20' 33 | main: 'dist/setup/index.js' 34 | post: 'dist/save-cache/index.js' 35 | post-if: success() 36 | branding: 37 | icon: 'package' 38 | color: 'blue' -------------------------------------------------------------------------------- /dist/setup/37.index.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | exports.id = 37; 3 | exports.ids = [37]; 4 | exports.modules = { 5 | 6 | /***/ 4037: 7 | /***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => { 8 | 9 | __webpack_require__.r(__webpack_exports__); 10 | /* harmony export */ __webpack_require__.d(__webpack_exports__, { 11 | /* harmony export */ "toFormData": () => (/* binding */ toFormData) 12 | /* harmony export */ }); 13 | /* harmony import */ var fetch_blob_from_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(2777); 14 | /* harmony import */ var formdata_polyfill_esm_min_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(8010); 15 | 16 | 17 | 18 | let s = 0; 19 | const S = { 20 | START_BOUNDARY: s++, 21 | HEADER_FIELD_START: s++, 22 | HEADER_FIELD: s++, 23 | HEADER_VALUE_START: s++, 24 | HEADER_VALUE: s++, 25 | HEADER_VALUE_ALMOST_DONE: s++, 26 | HEADERS_ALMOST_DONE: s++, 27 | PART_DATA_START: s++, 28 | PART_DATA: s++, 29 | END: s++ 30 | }; 31 | 32 | let f = 1; 33 | const F = { 34 | PART_BOUNDARY: f, 35 | LAST_BOUNDARY: f *= 2 36 | }; 37 | 38 | const LF = 10; 39 | const CR = 13; 40 | const SPACE = 32; 41 | const HYPHEN = 45; 42 | const COLON = 58; 43 | const A = 97; 44 | const Z = 122; 45 | 46 | const lower = c => c | 0x20; 47 | 48 | const noop = () => {}; 49 | 50 | class MultipartParser { 51 | /** 52 | * @param {string} boundary 53 | */ 54 | constructor(boundary) { 55 | this.index = 0; 56 | this.flags = 0; 57 | 58 | this.onHeaderEnd = noop; 59 | this.onHeaderField = noop; 60 | this.onHeadersEnd = noop; 61 | this.onHeaderValue = noop; 62 | this.onPartBegin = noop; 63 | this.onPartData = noop; 64 | this.onPartEnd = noop; 65 | 66 | this.boundaryChars = {}; 67 | 68 | boundary = '\r\n--' + boundary; 69 | const ui8a = new Uint8Array(boundary.length); 70 | for (let i = 0; i < boundary.length; i++) { 71 | ui8a[i] = boundary.charCodeAt(i); 72 | this.boundaryChars[ui8a[i]] = true; 73 | } 74 | 75 | this.boundary = ui8a; 76 | this.lookbehind = new Uint8Array(this.boundary.length + 8); 77 | this.state = S.START_BOUNDARY; 78 | } 79 | 80 | /** 81 | * @param {Uint8Array} data 82 | */ 83 | write(data) { 84 | let i = 0; 85 | const length_ = data.length; 86 | let previousIndex = this.index; 87 | let {lookbehind, boundary, boundaryChars, index, state, flags} = this; 88 | const boundaryLength = this.boundary.length; 89 | const boundaryEnd = boundaryLength - 1; 90 | const bufferLength = data.length; 91 | let c; 92 | let cl; 93 | 94 | const mark = name => { 95 | this[name + 'Mark'] = i; 96 | }; 97 | 98 | const clear = name => { 99 | delete this[name + 'Mark']; 100 | }; 101 | 102 | const callback = (callbackSymbol, start, end, ui8a) => { 103 | if (start === undefined || start !== end) { 104 | this[callbackSymbol](ui8a && ui8a.subarray(start, end)); 105 | } 106 | }; 107 | 108 | const dataCallback = (name, clear) => { 109 | const markSymbol = name + 'Mark'; 110 | if (!(markSymbol in this)) { 111 | return; 112 | } 113 | 114 | if (clear) { 115 | callback(name, this[markSymbol], i, data); 116 | delete this[markSymbol]; 117 | } else { 118 | callback(name, this[markSymbol], data.length, data); 119 | this[markSymbol] = 0; 120 | } 121 | }; 122 | 123 | for (i = 0; i < length_; i++) { 124 | c = data[i]; 125 | 126 | switch (state) { 127 | case S.START_BOUNDARY: 128 | if (index === boundary.length - 2) { 129 | if (c === HYPHEN) { 130 | flags |= F.LAST_BOUNDARY; 131 | } else if (c !== CR) { 132 | return; 133 | } 134 | 135 | index++; 136 | break; 137 | } else if (index - 1 === boundary.length - 2) { 138 | if (flags & F.LAST_BOUNDARY && c === HYPHEN) { 139 | state = S.END; 140 | flags = 0; 141 | } else if (!(flags & F.LAST_BOUNDARY) && c === LF) { 142 | index = 0; 143 | callback('onPartBegin'); 144 | state = S.HEADER_FIELD_START; 145 | } else { 146 | return; 147 | } 148 | 149 | break; 150 | } 151 | 152 | if (c !== boundary[index + 2]) { 153 | index = -2; 154 | } 155 | 156 | if (c === boundary[index + 2]) { 157 | index++; 158 | } 159 | 160 | break; 161 | case S.HEADER_FIELD_START: 162 | state = S.HEADER_FIELD; 163 | mark('onHeaderField'); 164 | index = 0; 165 | // falls through 166 | case S.HEADER_FIELD: 167 | if (c === CR) { 168 | clear('onHeaderField'); 169 | state = S.HEADERS_ALMOST_DONE; 170 | break; 171 | } 172 | 173 | index++; 174 | if (c === HYPHEN) { 175 | break; 176 | } 177 | 178 | if (c === COLON) { 179 | if (index === 1) { 180 | // empty header field 181 | return; 182 | } 183 | 184 | dataCallback('onHeaderField', true); 185 | state = S.HEADER_VALUE_START; 186 | break; 187 | } 188 | 189 | cl = lower(c); 190 | if (cl < A || cl > Z) { 191 | return; 192 | } 193 | 194 | break; 195 | case S.HEADER_VALUE_START: 196 | if (c === SPACE) { 197 | break; 198 | } 199 | 200 | mark('onHeaderValue'); 201 | state = S.HEADER_VALUE; 202 | // falls through 203 | case S.HEADER_VALUE: 204 | if (c === CR) { 205 | dataCallback('onHeaderValue', true); 206 | callback('onHeaderEnd'); 207 | state = S.HEADER_VALUE_ALMOST_DONE; 208 | } 209 | 210 | break; 211 | case S.HEADER_VALUE_ALMOST_DONE: 212 | if (c !== LF) { 213 | return; 214 | } 215 | 216 | state = S.HEADER_FIELD_START; 217 | break; 218 | case S.HEADERS_ALMOST_DONE: 219 | if (c !== LF) { 220 | return; 221 | } 222 | 223 | callback('onHeadersEnd'); 224 | state = S.PART_DATA_START; 225 | break; 226 | case S.PART_DATA_START: 227 | state = S.PART_DATA; 228 | mark('onPartData'); 229 | // falls through 230 | case S.PART_DATA: 231 | previousIndex = index; 232 | 233 | if (index === 0) { 234 | // boyer-moore derrived algorithm to safely skip non-boundary data 235 | i += boundaryEnd; 236 | while (i < bufferLength && !(data[i] in boundaryChars)) { 237 | i += boundaryLength; 238 | } 239 | 240 | i -= boundaryEnd; 241 | c = data[i]; 242 | } 243 | 244 | if (index < boundary.length) { 245 | if (boundary[index] === c) { 246 | if (index === 0) { 247 | dataCallback('onPartData', true); 248 | } 249 | 250 | index++; 251 | } else { 252 | index = 0; 253 | } 254 | } else if (index === boundary.length) { 255 | index++; 256 | if (c === CR) { 257 | // CR = part boundary 258 | flags |= F.PART_BOUNDARY; 259 | } else if (c === HYPHEN) { 260 | // HYPHEN = end boundary 261 | flags |= F.LAST_BOUNDARY; 262 | } else { 263 | index = 0; 264 | } 265 | } else if (index - 1 === boundary.length) { 266 | if (flags & F.PART_BOUNDARY) { 267 | index = 0; 268 | if (c === LF) { 269 | // unset the PART_BOUNDARY flag 270 | flags &= ~F.PART_BOUNDARY; 271 | callback('onPartEnd'); 272 | callback('onPartBegin'); 273 | state = S.HEADER_FIELD_START; 274 | break; 275 | } 276 | } else if (flags & F.LAST_BOUNDARY) { 277 | if (c === HYPHEN) { 278 | callback('onPartEnd'); 279 | state = S.END; 280 | flags = 0; 281 | } else { 282 | index = 0; 283 | } 284 | } else { 285 | index = 0; 286 | } 287 | } 288 | 289 | if (index > 0) { 290 | // when matching a possible boundary, keep a lookbehind reference 291 | // in case it turns out to be a false lead 292 | lookbehind[index - 1] = c; 293 | } else if (previousIndex > 0) { 294 | // if our boundary turned out to be rubbish, the captured lookbehind 295 | // belongs to partData 296 | const _lookbehind = new Uint8Array(lookbehind.buffer, lookbehind.byteOffset, lookbehind.byteLength); 297 | callback('onPartData', 0, previousIndex, _lookbehind); 298 | previousIndex = 0; 299 | mark('onPartData'); 300 | 301 | // reconsider the current character even so it interrupted the sequence 302 | // it could be the beginning of a new sequence 303 | i--; 304 | } 305 | 306 | break; 307 | case S.END: 308 | break; 309 | default: 310 | throw new Error(`Unexpected state entered: ${state}`); 311 | } 312 | } 313 | 314 | dataCallback('onHeaderField'); 315 | dataCallback('onHeaderValue'); 316 | dataCallback('onPartData'); 317 | 318 | // Update properties for the next call 319 | this.index = index; 320 | this.state = state; 321 | this.flags = flags; 322 | } 323 | 324 | end() { 325 | if ((this.state === S.HEADER_FIELD_START && this.index === 0) || 326 | (this.state === S.PART_DATA && this.index === this.boundary.length)) { 327 | this.onPartEnd(); 328 | } else if (this.state !== S.END) { 329 | throw new Error('MultipartParser.end(): stream ended unexpectedly'); 330 | } 331 | } 332 | } 333 | 334 | function _fileName(headerValue) { 335 | // matches either a quoted-string or a token (RFC 2616 section 19.5.1) 336 | const m = headerValue.match(/\bfilename=("(.*?)"|([^()<>@,;:\\"/[\]?={}\s\t]+))($|;\s)/i); 337 | if (!m) { 338 | return; 339 | } 340 | 341 | const match = m[2] || m[3] || ''; 342 | let filename = match.slice(match.lastIndexOf('\\') + 1); 343 | filename = filename.replace(/%22/g, '"'); 344 | filename = filename.replace(/&#(\d{4});/g, (m, code) => { 345 | return String.fromCharCode(code); 346 | }); 347 | return filename; 348 | } 349 | 350 | async function toFormData(Body, ct) { 351 | if (!/multipart/i.test(ct)) { 352 | throw new TypeError('Failed to fetch'); 353 | } 354 | 355 | const m = ct.match(/boundary=(?:"([^"]+)"|([^;]+))/i); 356 | 357 | if (!m) { 358 | throw new TypeError('no or bad content-type header, no multipart boundary'); 359 | } 360 | 361 | const parser = new MultipartParser(m[1] || m[2]); 362 | 363 | let headerField; 364 | let headerValue; 365 | let entryValue; 366 | let entryName; 367 | let contentType; 368 | let filename; 369 | const entryChunks = []; 370 | const formData = new formdata_polyfill_esm_min_js__WEBPACK_IMPORTED_MODULE_1__/* .FormData */ .Ct(); 371 | 372 | const onPartData = ui8a => { 373 | entryValue += decoder.decode(ui8a, {stream: true}); 374 | }; 375 | 376 | const appendToFile = ui8a => { 377 | entryChunks.push(ui8a); 378 | }; 379 | 380 | const appendFileToFormData = () => { 381 | const file = new fetch_blob_from_js__WEBPACK_IMPORTED_MODULE_0__/* .File */ .$B(entryChunks, filename, {type: contentType}); 382 | formData.append(entryName, file); 383 | }; 384 | 385 | const appendEntryToFormData = () => { 386 | formData.append(entryName, entryValue); 387 | }; 388 | 389 | const decoder = new TextDecoder('utf-8'); 390 | decoder.decode(); 391 | 392 | parser.onPartBegin = function () { 393 | parser.onPartData = onPartData; 394 | parser.onPartEnd = appendEntryToFormData; 395 | 396 | headerField = ''; 397 | headerValue = ''; 398 | entryValue = ''; 399 | entryName = ''; 400 | contentType = ''; 401 | filename = null; 402 | entryChunks.length = 0; 403 | }; 404 | 405 | parser.onHeaderField = function (ui8a) { 406 | headerField += decoder.decode(ui8a, {stream: true}); 407 | }; 408 | 409 | parser.onHeaderValue = function (ui8a) { 410 | headerValue += decoder.decode(ui8a, {stream: true}); 411 | }; 412 | 413 | parser.onHeaderEnd = function () { 414 | headerValue += decoder.decode(); 415 | headerField = headerField.toLowerCase(); 416 | 417 | if (headerField === 'content-disposition') { 418 | // matches either a quoted-string or a token (RFC 2616 section 19.5.1) 419 | const m = headerValue.match(/\bname=("([^"]*)"|([^()<>@,;:\\"/[\]?={}\s\t]+))/i); 420 | 421 | if (m) { 422 | entryName = m[2] || m[3] || ''; 423 | } 424 | 425 | filename = _fileName(headerValue); 426 | 427 | if (filename) { 428 | parser.onPartData = appendToFile; 429 | parser.onPartEnd = appendFileToFormData; 430 | } 431 | } else if (headerField === 'content-type') { 432 | contentType = headerValue; 433 | } 434 | 435 | headerValue = ''; 436 | headerField = ''; 437 | }; 438 | 439 | for await (const chunk of Body) { 440 | parser.write(chunk); 441 | } 442 | 443 | parser.end(); 444 | 445 | return formData; 446 | } 447 | 448 | 449 | /***/ }) 450 | 451 | }; 452 | ; 453 | //# sourceMappingURL=37.index.js.map -------------------------------------------------------------------------------- /dist/setup/37.index.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"file":"37.index.js","mappings":";;;;;;;;;;;;;;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA","sources":[".././node_modules/node-fetch/src/utils/multipart-parser.js"],"sourcesContent":["import {File} from 'fetch-blob/from.js';\nimport {FormData} from 'formdata-polyfill/esm.min.js';\n\nlet s = 0;\nconst S = {\n\tSTART_BOUNDARY: s++,\n\tHEADER_FIELD_START: s++,\n\tHEADER_FIELD: s++,\n\tHEADER_VALUE_START: s++,\n\tHEADER_VALUE: s++,\n\tHEADER_VALUE_ALMOST_DONE: s++,\n\tHEADERS_ALMOST_DONE: s++,\n\tPART_DATA_START: s++,\n\tPART_DATA: s++,\n\tEND: s++\n};\n\nlet f = 1;\nconst F = {\n\tPART_BOUNDARY: f,\n\tLAST_BOUNDARY: f *= 2\n};\n\nconst LF = 10;\nconst CR = 13;\nconst SPACE = 32;\nconst HYPHEN = 45;\nconst COLON = 58;\nconst A = 97;\nconst Z = 122;\n\nconst lower = c => c | 0x20;\n\nconst noop = () => {};\n\nclass MultipartParser {\n\t/**\n\t * @param {string} boundary\n\t */\n\tconstructor(boundary) {\n\t\tthis.index = 0;\n\t\tthis.flags = 0;\n\n\t\tthis.onHeaderEnd = noop;\n\t\tthis.onHeaderField = noop;\n\t\tthis.onHeadersEnd = noop;\n\t\tthis.onHeaderValue = noop;\n\t\tthis.onPartBegin = noop;\n\t\tthis.onPartData = noop;\n\t\tthis.onPartEnd = noop;\n\n\t\tthis.boundaryChars = {};\n\n\t\tboundary = '\\r\\n--' + boundary;\n\t\tconst ui8a = new Uint8Array(boundary.length);\n\t\tfor (let i = 0; i < boundary.length; i++) {\n\t\t\tui8a[i] = boundary.charCodeAt(i);\n\t\t\tthis.boundaryChars[ui8a[i]] = true;\n\t\t}\n\n\t\tthis.boundary = ui8a;\n\t\tthis.lookbehind = new Uint8Array(this.boundary.length + 8);\n\t\tthis.state = S.START_BOUNDARY;\n\t}\n\n\t/**\n\t * @param {Uint8Array} data\n\t */\n\twrite(data) {\n\t\tlet i = 0;\n\t\tconst length_ = data.length;\n\t\tlet previousIndex = this.index;\n\t\tlet {lookbehind, boundary, boundaryChars, index, state, flags} = this;\n\t\tconst boundaryLength = this.boundary.length;\n\t\tconst boundaryEnd = boundaryLength - 1;\n\t\tconst bufferLength = data.length;\n\t\tlet c;\n\t\tlet cl;\n\n\t\tconst mark = name => {\n\t\t\tthis[name + 'Mark'] = i;\n\t\t};\n\n\t\tconst clear = name => {\n\t\t\tdelete this[name + 'Mark'];\n\t\t};\n\n\t\tconst callback = (callbackSymbol, start, end, ui8a) => {\n\t\t\tif (start === undefined || start !== end) {\n\t\t\t\tthis[callbackSymbol](ui8a && ui8a.subarray(start, end));\n\t\t\t}\n\t\t};\n\n\t\tconst dataCallback = (name, clear) => {\n\t\t\tconst markSymbol = name + 'Mark';\n\t\t\tif (!(markSymbol in this)) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tif (clear) {\n\t\t\t\tcallback(name, this[markSymbol], i, data);\n\t\t\t\tdelete this[markSymbol];\n\t\t\t} else {\n\t\t\t\tcallback(name, this[markSymbol], data.length, data);\n\t\t\t\tthis[markSymbol] = 0;\n\t\t\t}\n\t\t};\n\n\t\tfor (i = 0; i < length_; i++) {\n\t\t\tc = data[i];\n\n\t\t\tswitch (state) {\n\t\t\t\tcase S.START_BOUNDARY:\n\t\t\t\t\tif (index === boundary.length - 2) {\n\t\t\t\t\t\tif (c === HYPHEN) {\n\t\t\t\t\t\t\tflags |= F.LAST_BOUNDARY;\n\t\t\t\t\t\t} else if (c !== CR) {\n\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tindex++;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t} else if (index - 1 === boundary.length - 2) {\n\t\t\t\t\t\tif (flags & F.LAST_BOUNDARY && c === HYPHEN) {\n\t\t\t\t\t\t\tstate = S.END;\n\t\t\t\t\t\t\tflags = 0;\n\t\t\t\t\t\t} else if (!(flags & F.LAST_BOUNDARY) && c === LF) {\n\t\t\t\t\t\t\tindex = 0;\n\t\t\t\t\t\t\tcallback('onPartBegin');\n\t\t\t\t\t\t\tstate = S.HEADER_FIELD_START;\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\n\t\t\t\t\tif (c !== boundary[index + 2]) {\n\t\t\t\t\t\tindex = -2;\n\t\t\t\t\t}\n\n\t\t\t\t\tif (c === boundary[index + 2]) {\n\t\t\t\t\t\tindex++;\n\t\t\t\t\t}\n\n\t\t\t\t\tbreak;\n\t\t\t\tcase S.HEADER_FIELD_START:\n\t\t\t\t\tstate = S.HEADER_FIELD;\n\t\t\t\t\tmark('onHeaderField');\n\t\t\t\t\tindex = 0;\n\t\t\t\t\t// falls through\n\t\t\t\tcase S.HEADER_FIELD:\n\t\t\t\t\tif (c === CR) {\n\t\t\t\t\t\tclear('onHeaderField');\n\t\t\t\t\t\tstate = S.HEADERS_ALMOST_DONE;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\n\t\t\t\t\tindex++;\n\t\t\t\t\tif (c === HYPHEN) {\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\n\t\t\t\t\tif (c === COLON) {\n\t\t\t\t\t\tif (index === 1) {\n\t\t\t\t\t\t\t// empty header field\n\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tdataCallback('onHeaderField', true);\n\t\t\t\t\t\tstate = S.HEADER_VALUE_START;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\n\t\t\t\t\tcl = lower(c);\n\t\t\t\t\tif (cl < A || cl > Z) {\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\n\t\t\t\t\tbreak;\n\t\t\t\tcase S.HEADER_VALUE_START:\n\t\t\t\t\tif (c === SPACE) {\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\n\t\t\t\t\tmark('onHeaderValue');\n\t\t\t\t\tstate = S.HEADER_VALUE;\n\t\t\t\t\t// falls through\n\t\t\t\tcase S.HEADER_VALUE:\n\t\t\t\t\tif (c === CR) {\n\t\t\t\t\t\tdataCallback('onHeaderValue', true);\n\t\t\t\t\t\tcallback('onHeaderEnd');\n\t\t\t\t\t\tstate = S.HEADER_VALUE_ALMOST_DONE;\n\t\t\t\t\t}\n\n\t\t\t\t\tbreak;\n\t\t\t\tcase S.HEADER_VALUE_ALMOST_DONE:\n\t\t\t\t\tif (c !== LF) {\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\n\t\t\t\t\tstate = S.HEADER_FIELD_START;\n\t\t\t\t\tbreak;\n\t\t\t\tcase S.HEADERS_ALMOST_DONE:\n\t\t\t\t\tif (c !== LF) {\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\n\t\t\t\t\tcallback('onHeadersEnd');\n\t\t\t\t\tstate = S.PART_DATA_START;\n\t\t\t\t\tbreak;\n\t\t\t\tcase S.PART_DATA_START:\n\t\t\t\t\tstate = S.PART_DATA;\n\t\t\t\t\tmark('onPartData');\n\t\t\t\t\t// falls through\n\t\t\t\tcase S.PART_DATA:\n\t\t\t\t\tpreviousIndex = index;\n\n\t\t\t\t\tif (index === 0) {\n\t\t\t\t\t\t// boyer-moore derrived algorithm to safely skip non-boundary data\n\t\t\t\t\t\ti += boundaryEnd;\n\t\t\t\t\t\twhile (i < bufferLength && !(data[i] in boundaryChars)) {\n\t\t\t\t\t\t\ti += boundaryLength;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\ti -= boundaryEnd;\n\t\t\t\t\t\tc = data[i];\n\t\t\t\t\t}\n\n\t\t\t\t\tif (index < boundary.length) {\n\t\t\t\t\t\tif (boundary[index] === c) {\n\t\t\t\t\t\t\tif (index === 0) {\n\t\t\t\t\t\t\t\tdataCallback('onPartData', true);\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\tindex++;\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tindex = 0;\n\t\t\t\t\t\t}\n\t\t\t\t\t} else if (index === boundary.length) {\n\t\t\t\t\t\tindex++;\n\t\t\t\t\t\tif (c === CR) {\n\t\t\t\t\t\t\t// CR = part boundary\n\t\t\t\t\t\t\tflags |= F.PART_BOUNDARY;\n\t\t\t\t\t\t} else if (c === HYPHEN) {\n\t\t\t\t\t\t\t// HYPHEN = end boundary\n\t\t\t\t\t\t\tflags |= F.LAST_BOUNDARY;\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tindex = 0;\n\t\t\t\t\t\t}\n\t\t\t\t\t} else if (index - 1 === boundary.length) {\n\t\t\t\t\t\tif (flags & F.PART_BOUNDARY) {\n\t\t\t\t\t\t\tindex = 0;\n\t\t\t\t\t\t\tif (c === LF) {\n\t\t\t\t\t\t\t\t// unset the PART_BOUNDARY flag\n\t\t\t\t\t\t\t\tflags &= ~F.PART_BOUNDARY;\n\t\t\t\t\t\t\t\tcallback('onPartEnd');\n\t\t\t\t\t\t\t\tcallback('onPartBegin');\n\t\t\t\t\t\t\t\tstate = S.HEADER_FIELD_START;\n\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} else if (flags & F.LAST_BOUNDARY) {\n\t\t\t\t\t\t\tif (c === HYPHEN) {\n\t\t\t\t\t\t\t\tcallback('onPartEnd');\n\t\t\t\t\t\t\t\tstate = S.END;\n\t\t\t\t\t\t\t\tflags = 0;\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\tindex = 0;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tindex = 0;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tif (index > 0) {\n\t\t\t\t\t\t// when matching a possible boundary, keep a lookbehind reference\n\t\t\t\t\t\t// in case it turns out to be a false lead\n\t\t\t\t\t\tlookbehind[index - 1] = c;\n\t\t\t\t\t} else if (previousIndex > 0) {\n\t\t\t\t\t\t// if our boundary turned out to be rubbish, the captured lookbehind\n\t\t\t\t\t\t// belongs to partData\n\t\t\t\t\t\tconst _lookbehind = new Uint8Array(lookbehind.buffer, lookbehind.byteOffset, lookbehind.byteLength);\n\t\t\t\t\t\tcallback('onPartData', 0, previousIndex, _lookbehind);\n\t\t\t\t\t\tpreviousIndex = 0;\n\t\t\t\t\t\tmark('onPartData');\n\n\t\t\t\t\t\t// reconsider the current character even so it interrupted the sequence\n\t\t\t\t\t\t// it could be the beginning of a new sequence\n\t\t\t\t\t\ti--;\n\t\t\t\t\t}\n\n\t\t\t\t\tbreak;\n\t\t\t\tcase S.END:\n\t\t\t\t\tbreak;\n\t\t\t\tdefault:\n\t\t\t\t\tthrow new Error(`Unexpected state entered: ${state}`);\n\t\t\t}\n\t\t}\n\n\t\tdataCallback('onHeaderField');\n\t\tdataCallback('onHeaderValue');\n\t\tdataCallback('onPartData');\n\n\t\t// Update properties for the next call\n\t\tthis.index = index;\n\t\tthis.state = state;\n\t\tthis.flags = flags;\n\t}\n\n\tend() {\n\t\tif ((this.state === S.HEADER_FIELD_START && this.index === 0) ||\n\t\t\t(this.state === S.PART_DATA && this.index === this.boundary.length)) {\n\t\t\tthis.onPartEnd();\n\t\t} else if (this.state !== S.END) {\n\t\t\tthrow new Error('MultipartParser.end(): stream ended unexpectedly');\n\t\t}\n\t}\n}\n\nfunction _fileName(headerValue) {\n\t// matches either a quoted-string or a token (RFC 2616 section 19.5.1)\n\tconst m = headerValue.match(/\\bfilename=(\"(.*?)\"|([^()<>@,;:\\\\\"/[\\]?={}\\s\\t]+))($|;\\s)/i);\n\tif (!m) {\n\t\treturn;\n\t}\n\n\tconst match = m[2] || m[3] || '';\n\tlet filename = match.slice(match.lastIndexOf('\\\\') + 1);\n\tfilename = filename.replace(/%22/g, '\"');\n\tfilename = filename.replace(/&#(\\d{4});/g, (m, code) => {\n\t\treturn String.fromCharCode(code);\n\t});\n\treturn filename;\n}\n\nexport async function toFormData(Body, ct) {\n\tif (!/multipart/i.test(ct)) {\n\t\tthrow new TypeError('Failed to fetch');\n\t}\n\n\tconst m = ct.match(/boundary=(?:\"([^\"]+)\"|([^;]+))/i);\n\n\tif (!m) {\n\t\tthrow new TypeError('no or bad content-type header, no multipart boundary');\n\t}\n\n\tconst parser = new MultipartParser(m[1] || m[2]);\n\n\tlet headerField;\n\tlet headerValue;\n\tlet entryValue;\n\tlet entryName;\n\tlet contentType;\n\tlet filename;\n\tconst entryChunks = [];\n\tconst formData = new FormData();\n\n\tconst onPartData = ui8a => {\n\t\tentryValue += decoder.decode(ui8a, {stream: true});\n\t};\n\n\tconst appendToFile = ui8a => {\n\t\tentryChunks.push(ui8a);\n\t};\n\n\tconst appendFileToFormData = () => {\n\t\tconst file = new File(entryChunks, filename, {type: contentType});\n\t\tformData.append(entryName, file);\n\t};\n\n\tconst appendEntryToFormData = () => {\n\t\tformData.append(entryName, entryValue);\n\t};\n\n\tconst decoder = new TextDecoder('utf-8');\n\tdecoder.decode();\n\n\tparser.onPartBegin = function () {\n\t\tparser.onPartData = onPartData;\n\t\tparser.onPartEnd = appendEntryToFormData;\n\n\t\theaderField = '';\n\t\theaderValue = '';\n\t\tentryValue = '';\n\t\tentryName = '';\n\t\tcontentType = '';\n\t\tfilename = null;\n\t\tentryChunks.length = 0;\n\t};\n\n\tparser.onHeaderField = function (ui8a) {\n\t\theaderField += decoder.decode(ui8a, {stream: true});\n\t};\n\n\tparser.onHeaderValue = function (ui8a) {\n\t\theaderValue += decoder.decode(ui8a, {stream: true});\n\t};\n\n\tparser.onHeaderEnd = function () {\n\t\theaderValue += decoder.decode();\n\t\theaderField = headerField.toLowerCase();\n\n\t\tif (headerField === 'content-disposition') {\n\t\t\t// matches either a quoted-string or a token (RFC 2616 section 19.5.1)\n\t\t\tconst m = headerValue.match(/\\bname=(\"([^\"]*)\"|([^()<>@,;:\\\\\"/[\\]?={}\\s\\t]+))/i);\n\n\t\t\tif (m) {\n\t\t\t\tentryName = m[2] || m[3] || '';\n\t\t\t}\n\n\t\t\tfilename = _fileName(headerValue);\n\n\t\t\tif (filename) {\n\t\t\t\tparser.onPartData = appendToFile;\n\t\t\t\tparser.onPartEnd = appendFileToFormData;\n\t\t\t}\n\t\t} else if (headerField === 'content-type') {\n\t\t\tcontentType = headerValue;\n\t\t}\n\n\t\theaderValue = '';\n\t\theaderField = '';\n\t};\n\n\tfor await (const chunk of Body) {\n\t\tparser.write(chunk);\n\t}\n\n\tparser.end();\n\n\treturn formData;\n}\n"],"names":[],"sourceRoot":""} -------------------------------------------------------------------------------- /dist/setup/sourcemap-register.js: -------------------------------------------------------------------------------- 1 | (()=>{var e={650:e=>{var r=Object.prototype.toString;var n=typeof Buffer.alloc==="function"&&typeof Buffer.allocUnsafe==="function"&&typeof Buffer.from==="function";function isArrayBuffer(e){return r.call(e).slice(8,-1)==="ArrayBuffer"}function fromArrayBuffer(e,r,t){r>>>=0;var o=e.byteLength-r;if(o<0){throw new RangeError("'offset' is out of bounds")}if(t===undefined){t=o}else{t>>>=0;if(t>o){throw new RangeError("'length' is out of bounds")}}return n?Buffer.from(e.slice(r,r+t)):new Buffer(new Uint8Array(e.slice(r,r+t)))}function fromString(e,r){if(typeof r!=="string"||r===""){r="utf8"}if(!Buffer.isEncoding(r)){throw new TypeError('"encoding" must be a valid string encoding')}return n?Buffer.from(e,r):new Buffer(e,r)}function bufferFrom(e,r,t){if(typeof e==="number"){throw new TypeError('"value" argument must not be a number')}if(isArrayBuffer(e)){return fromArrayBuffer(e,r,t)}if(typeof e==="string"){return fromString(e,r)}return n?Buffer.from(e):new Buffer(e)}e.exports=bufferFrom},274:(e,r,n)=>{var t=n(339);var o=Object.prototype.hasOwnProperty;var i=typeof Map!=="undefined";function ArraySet(){this._array=[];this._set=i?new Map:Object.create(null)}ArraySet.fromArray=function ArraySet_fromArray(e,r){var n=new ArraySet;for(var t=0,o=e.length;t=0){return r}}else{var n=t.toSetString(e);if(o.call(this._set,n)){return this._set[n]}}throw new Error('"'+e+'" is not in the set.')};ArraySet.prototype.at=function ArraySet_at(e){if(e>=0&&e{var t=n(190);var o=5;var i=1<>1;return r?-n:n}r.encode=function base64VLQ_encode(e){var r="";var n;var i=toVLQSigned(e);do{n=i&a;i>>>=o;if(i>0){n|=u}r+=t.encode(n)}while(i>0);return r};r.decode=function base64VLQ_decode(e,r,n){var i=e.length;var s=0;var l=0;var c,p;do{if(r>=i){throw new Error("Expected more digits in base 64 VLQ value.")}p=t.decode(e.charCodeAt(r++));if(p===-1){throw new Error("Invalid base64 digit: "+e.charAt(r-1))}c=!!(p&u);p&=a;s=s+(p<{var n="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/".split("");r.encode=function(e){if(0<=e&&e{r.GREATEST_LOWER_BOUND=1;r.LEAST_UPPER_BOUND=2;function recursiveSearch(e,n,t,o,i,a){var u=Math.floor((n-e)/2)+e;var s=i(t,o[u],true);if(s===0){return u}else if(s>0){if(n-u>1){return recursiveSearch(u,n,t,o,i,a)}if(a==r.LEAST_UPPER_BOUND){return n1){return recursiveSearch(e,u,t,o,i,a)}if(a==r.LEAST_UPPER_BOUND){return u}else{return e<0?-1:e}}}r.search=function search(e,n,t,o){if(n.length===0){return-1}var i=recursiveSearch(-1,n.length,e,n,t,o||r.GREATEST_LOWER_BOUND);if(i<0){return-1}while(i-1>=0){if(t(n[i],n[i-1],true)!==0){break}--i}return i}},680:(e,r,n)=>{var t=n(339);function generatedPositionAfter(e,r){var n=e.generatedLine;var o=r.generatedLine;var i=e.generatedColumn;var a=r.generatedColumn;return o>n||o==n&&a>=i||t.compareByGeneratedPositionsInflated(e,r)<=0}function MappingList(){this._array=[];this._sorted=true;this._last={generatedLine:-1,generatedColumn:0}}MappingList.prototype.unsortedForEach=function MappingList_forEach(e,r){this._array.forEach(e,r)};MappingList.prototype.add=function MappingList_add(e){if(generatedPositionAfter(this._last,e)){this._last=e;this._array.push(e)}else{this._sorted=false;this._array.push(e)}};MappingList.prototype.toArray=function MappingList_toArray(){if(!this._sorted){this._array.sort(t.compareByGeneratedPositionsInflated);this._sorted=true}return this._array};r.H=MappingList},758:(e,r)=>{function swap(e,r,n){var t=e[r];e[r]=e[n];e[n]=t}function randomIntInRange(e,r){return Math.round(e+Math.random()*(r-e))}function doQuickSort(e,r,n,t){if(n{var t;var o=n(339);var i=n(345);var a=n(274).I;var u=n(449);var s=n(758).U;function SourceMapConsumer(e,r){var n=e;if(typeof e==="string"){n=o.parseSourceMapInput(e)}return n.sections!=null?new IndexedSourceMapConsumer(n,r):new BasicSourceMapConsumer(n,r)}SourceMapConsumer.fromSourceMap=function(e,r){return BasicSourceMapConsumer.fromSourceMap(e,r)};SourceMapConsumer.prototype._version=3;SourceMapConsumer.prototype.__generatedMappings=null;Object.defineProperty(SourceMapConsumer.prototype,"_generatedMappings",{configurable:true,enumerable:true,get:function(){if(!this.__generatedMappings){this._parseMappings(this._mappings,this.sourceRoot)}return this.__generatedMappings}});SourceMapConsumer.prototype.__originalMappings=null;Object.defineProperty(SourceMapConsumer.prototype,"_originalMappings",{configurable:true,enumerable:true,get:function(){if(!this.__originalMappings){this._parseMappings(this._mappings,this.sourceRoot)}return this.__originalMappings}});SourceMapConsumer.prototype._charIsMappingSeparator=function SourceMapConsumer_charIsMappingSeparator(e,r){var n=e.charAt(r);return n===";"||n===","};SourceMapConsumer.prototype._parseMappings=function SourceMapConsumer_parseMappings(e,r){throw new Error("Subclasses must implement _parseMappings")};SourceMapConsumer.GENERATED_ORDER=1;SourceMapConsumer.ORIGINAL_ORDER=2;SourceMapConsumer.GREATEST_LOWER_BOUND=1;SourceMapConsumer.LEAST_UPPER_BOUND=2;SourceMapConsumer.prototype.eachMapping=function SourceMapConsumer_eachMapping(e,r,n){var t=r||null;var i=n||SourceMapConsumer.GENERATED_ORDER;var a;switch(i){case SourceMapConsumer.GENERATED_ORDER:a=this._generatedMappings;break;case SourceMapConsumer.ORIGINAL_ORDER:a=this._originalMappings;break;default:throw new Error("Unknown order of iteration.")}var u=this.sourceRoot;a.map((function(e){var r=e.source===null?null:this._sources.at(e.source);r=o.computeSourceURL(u,r,this._sourceMapURL);return{source:r,generatedLine:e.generatedLine,generatedColumn:e.generatedColumn,originalLine:e.originalLine,originalColumn:e.originalColumn,name:e.name===null?null:this._names.at(e.name)}}),this).forEach(e,t)};SourceMapConsumer.prototype.allGeneratedPositionsFor=function SourceMapConsumer_allGeneratedPositionsFor(e){var r=o.getArg(e,"line");var n={source:o.getArg(e,"source"),originalLine:r,originalColumn:o.getArg(e,"column",0)};n.source=this._findSourceIndex(n.source);if(n.source<0){return[]}var t=[];var a=this._findMapping(n,this._originalMappings,"originalLine","originalColumn",o.compareByOriginalPositions,i.LEAST_UPPER_BOUND);if(a>=0){var u=this._originalMappings[a];if(e.column===undefined){var s=u.originalLine;while(u&&u.originalLine===s){t.push({line:o.getArg(u,"generatedLine",null),column:o.getArg(u,"generatedColumn",null),lastColumn:o.getArg(u,"lastGeneratedColumn",null)});u=this._originalMappings[++a]}}else{var l=u.originalColumn;while(u&&u.originalLine===r&&u.originalColumn==l){t.push({line:o.getArg(u,"generatedLine",null),column:o.getArg(u,"generatedColumn",null),lastColumn:o.getArg(u,"lastGeneratedColumn",null)});u=this._originalMappings[++a]}}}return t};r.SourceMapConsumer=SourceMapConsumer;function BasicSourceMapConsumer(e,r){var n=e;if(typeof e==="string"){n=o.parseSourceMapInput(e)}var t=o.getArg(n,"version");var i=o.getArg(n,"sources");var u=o.getArg(n,"names",[]);var s=o.getArg(n,"sourceRoot",null);var l=o.getArg(n,"sourcesContent",null);var c=o.getArg(n,"mappings");var p=o.getArg(n,"file",null);if(t!=this._version){throw new Error("Unsupported version: "+t)}if(s){s=o.normalize(s)}i=i.map(String).map(o.normalize).map((function(e){return s&&o.isAbsolute(s)&&o.isAbsolute(e)?o.relative(s,e):e}));this._names=a.fromArray(u.map(String),true);this._sources=a.fromArray(i,true);this._absoluteSources=this._sources.toArray().map((function(e){return o.computeSourceURL(s,e,r)}));this.sourceRoot=s;this.sourcesContent=l;this._mappings=c;this._sourceMapURL=r;this.file=p}BasicSourceMapConsumer.prototype=Object.create(SourceMapConsumer.prototype);BasicSourceMapConsumer.prototype.consumer=SourceMapConsumer;BasicSourceMapConsumer.prototype._findSourceIndex=function(e){var r=e;if(this.sourceRoot!=null){r=o.relative(this.sourceRoot,r)}if(this._sources.has(r)){return this._sources.indexOf(r)}var n;for(n=0;n1){v.source=l+_[1];l+=_[1];v.originalLine=i+_[2];i=v.originalLine;v.originalLine+=1;v.originalColumn=a+_[3];a=v.originalColumn;if(_.length>4){v.name=c+_[4];c+=_[4]}}m.push(v);if(typeof v.originalLine==="number"){d.push(v)}}}s(m,o.compareByGeneratedPositionsDeflated);this.__generatedMappings=m;s(d,o.compareByOriginalPositions);this.__originalMappings=d};BasicSourceMapConsumer.prototype._findMapping=function SourceMapConsumer_findMapping(e,r,n,t,o,a){if(e[n]<=0){throw new TypeError("Line must be greater than or equal to 1, got "+e[n])}if(e[t]<0){throw new TypeError("Column must be greater than or equal to 0, got "+e[t])}return i.search(e,r,o,a)};BasicSourceMapConsumer.prototype.computeColumnSpans=function SourceMapConsumer_computeColumnSpans(){for(var e=0;e=0){var t=this._generatedMappings[n];if(t.generatedLine===r.generatedLine){var i=o.getArg(t,"source",null);if(i!==null){i=this._sources.at(i);i=o.computeSourceURL(this.sourceRoot,i,this._sourceMapURL)}var a=o.getArg(t,"name",null);if(a!==null){a=this._names.at(a)}return{source:i,line:o.getArg(t,"originalLine",null),column:o.getArg(t,"originalColumn",null),name:a}}}return{source:null,line:null,column:null,name:null}};BasicSourceMapConsumer.prototype.hasContentsOfAllSources=function BasicSourceMapConsumer_hasContentsOfAllSources(){if(!this.sourcesContent){return false}return this.sourcesContent.length>=this._sources.size()&&!this.sourcesContent.some((function(e){return e==null}))};BasicSourceMapConsumer.prototype.sourceContentFor=function SourceMapConsumer_sourceContentFor(e,r){if(!this.sourcesContent){return null}var n=this._findSourceIndex(e);if(n>=0){return this.sourcesContent[n]}var t=e;if(this.sourceRoot!=null){t=o.relative(this.sourceRoot,t)}var i;if(this.sourceRoot!=null&&(i=o.urlParse(this.sourceRoot))){var a=t.replace(/^file:\/\//,"");if(i.scheme=="file"&&this._sources.has(a)){return this.sourcesContent[this._sources.indexOf(a)]}if((!i.path||i.path=="/")&&this._sources.has("/"+t)){return this.sourcesContent[this._sources.indexOf("/"+t)]}}if(r){return null}else{throw new Error('"'+t+'" is not in the SourceMap.')}};BasicSourceMapConsumer.prototype.generatedPositionFor=function SourceMapConsumer_generatedPositionFor(e){var r=o.getArg(e,"source");r=this._findSourceIndex(r);if(r<0){return{line:null,column:null,lastColumn:null}}var n={source:r,originalLine:o.getArg(e,"line"),originalColumn:o.getArg(e,"column")};var t=this._findMapping(n,this._originalMappings,"originalLine","originalColumn",o.compareByOriginalPositions,o.getArg(e,"bias",SourceMapConsumer.GREATEST_LOWER_BOUND));if(t>=0){var i=this._originalMappings[t];if(i.source===n.source){return{line:o.getArg(i,"generatedLine",null),column:o.getArg(i,"generatedColumn",null),lastColumn:o.getArg(i,"lastGeneratedColumn",null)}}}return{line:null,column:null,lastColumn:null}};t=BasicSourceMapConsumer;function IndexedSourceMapConsumer(e,r){var n=e;if(typeof e==="string"){n=o.parseSourceMapInput(e)}var t=o.getArg(n,"version");var i=o.getArg(n,"sections");if(t!=this._version){throw new Error("Unsupported version: "+t)}this._sources=new a;this._names=new a;var u={line:-1,column:0};this._sections=i.map((function(e){if(e.url){throw new Error("Support for url field in sections not implemented.")}var n=o.getArg(e,"offset");var t=o.getArg(n,"line");var i=o.getArg(n,"column");if(t{var t=n(449);var o=n(339);var i=n(274).I;var a=n(680).H;function SourceMapGenerator(e){if(!e){e={}}this._file=o.getArg(e,"file",null);this._sourceRoot=o.getArg(e,"sourceRoot",null);this._skipValidation=o.getArg(e,"skipValidation",false);this._sources=new i;this._names=new i;this._mappings=new a;this._sourcesContents=null}SourceMapGenerator.prototype._version=3;SourceMapGenerator.fromSourceMap=function SourceMapGenerator_fromSourceMap(e){var r=e.sourceRoot;var n=new SourceMapGenerator({file:e.file,sourceRoot:r});e.eachMapping((function(e){var t={generated:{line:e.generatedLine,column:e.generatedColumn}};if(e.source!=null){t.source=e.source;if(r!=null){t.source=o.relative(r,t.source)}t.original={line:e.originalLine,column:e.originalColumn};if(e.name!=null){t.name=e.name}}n.addMapping(t)}));e.sources.forEach((function(t){var i=t;if(r!==null){i=o.relative(r,t)}if(!n._sources.has(i)){n._sources.add(i)}var a=e.sourceContentFor(t);if(a!=null){n.setSourceContent(t,a)}}));return n};SourceMapGenerator.prototype.addMapping=function SourceMapGenerator_addMapping(e){var r=o.getArg(e,"generated");var n=o.getArg(e,"original",null);var t=o.getArg(e,"source",null);var i=o.getArg(e,"name",null);if(!this._skipValidation){this._validateMapping(r,n,t,i)}if(t!=null){t=String(t);if(!this._sources.has(t)){this._sources.add(t)}}if(i!=null){i=String(i);if(!this._names.has(i)){this._names.add(i)}}this._mappings.add({generatedLine:r.line,generatedColumn:r.column,originalLine:n!=null&&n.line,originalColumn:n!=null&&n.column,source:t,name:i})};SourceMapGenerator.prototype.setSourceContent=function SourceMapGenerator_setSourceContent(e,r){var n=e;if(this._sourceRoot!=null){n=o.relative(this._sourceRoot,n)}if(r!=null){if(!this._sourcesContents){this._sourcesContents=Object.create(null)}this._sourcesContents[o.toSetString(n)]=r}else if(this._sourcesContents){delete this._sourcesContents[o.toSetString(n)];if(Object.keys(this._sourcesContents).length===0){this._sourcesContents=null}}};SourceMapGenerator.prototype.applySourceMap=function SourceMapGenerator_applySourceMap(e,r,n){var t=r;if(r==null){if(e.file==null){throw new Error("SourceMapGenerator.prototype.applySourceMap requires either an explicit source file, "+'or the source map\'s "file" property. Both were omitted.')}t=e.file}var a=this._sourceRoot;if(a!=null){t=o.relative(a,t)}var u=new i;var s=new i;this._mappings.unsortedForEach((function(r){if(r.source===t&&r.originalLine!=null){var i=e.originalPositionFor({line:r.originalLine,column:r.originalColumn});if(i.source!=null){r.source=i.source;if(n!=null){r.source=o.join(n,r.source)}if(a!=null){r.source=o.relative(a,r.source)}r.originalLine=i.line;r.originalColumn=i.column;if(i.name!=null){r.name=i.name}}}var l=r.source;if(l!=null&&!u.has(l)){u.add(l)}var c=r.name;if(c!=null&&!s.has(c)){s.add(c)}}),this);this._sources=u;this._names=s;e.sources.forEach((function(r){var t=e.sourceContentFor(r);if(t!=null){if(n!=null){r=o.join(n,r)}if(a!=null){r=o.relative(a,r)}this.setSourceContent(r,t)}}),this)};SourceMapGenerator.prototype._validateMapping=function SourceMapGenerator_validateMapping(e,r,n,t){if(r&&typeof r.line!=="number"&&typeof r.column!=="number"){throw new Error("original.line and original.column are not numbers -- you probably meant to omit "+"the original mapping entirely and only map the generated position. If so, pass "+"null for the original mapping instead of an object with empty or null values.")}if(e&&"line"in e&&"column"in e&&e.line>0&&e.column>=0&&!r&&!n&&!t){return}else if(e&&"line"in e&&"column"in e&&r&&"line"in r&&"column"in r&&e.line>0&&e.column>=0&&r.line>0&&r.column>=0&&n){return}else{throw new Error("Invalid mapping: "+JSON.stringify({generated:e,source:n,original:r,name:t}))}};SourceMapGenerator.prototype._serializeMappings=function SourceMapGenerator_serializeMappings(){var e=0;var r=1;var n=0;var i=0;var a=0;var u=0;var s="";var l;var c;var p;var f;var g=this._mappings.toArray();for(var h=0,d=g.length;h0){if(!o.compareByGeneratedPositionsInflated(c,g[h-1])){continue}l+=","}}l+=t.encode(c.generatedColumn-e);e=c.generatedColumn;if(c.source!=null){f=this._sources.indexOf(c.source);l+=t.encode(f-u);u=f;l+=t.encode(c.originalLine-1-i);i=c.originalLine-1;l+=t.encode(c.originalColumn-n);n=c.originalColumn;if(c.name!=null){p=this._names.indexOf(c.name);l+=t.encode(p-a);a=p}}s+=l}return s};SourceMapGenerator.prototype._generateSourcesContent=function SourceMapGenerator_generateSourcesContent(e,r){return e.map((function(e){if(!this._sourcesContents){return null}if(r!=null){e=o.relative(r,e)}var n=o.toSetString(e);return Object.prototype.hasOwnProperty.call(this._sourcesContents,n)?this._sourcesContents[n]:null}),this)};SourceMapGenerator.prototype.toJSON=function SourceMapGenerator_toJSON(){var e={version:this._version,sources:this._sources.toArray(),names:this._names.toArray(),mappings:this._serializeMappings()};if(this._file!=null){e.file=this._file}if(this._sourceRoot!=null){e.sourceRoot=this._sourceRoot}if(this._sourcesContents){e.sourcesContent=this._generateSourcesContent(e.sources,e.sourceRoot)}return e};SourceMapGenerator.prototype.toString=function SourceMapGenerator_toString(){return JSON.stringify(this.toJSON())};r.h=SourceMapGenerator},351:(e,r,n)=>{var t;var o=n(591).h;var i=n(339);var a=/(\r?\n)/;var u=10;var s="$$$isSourceNode$$$";function SourceNode(e,r,n,t,o){this.children=[];this.sourceContents={};this.line=e==null?null:e;this.column=r==null?null:r;this.source=n==null?null:n;this.name=o==null?null:o;this[s]=true;if(t!=null)this.add(t)}SourceNode.fromStringWithSourceMap=function SourceNode_fromStringWithSourceMap(e,r,n){var t=new SourceNode;var o=e.split(a);var u=0;var shiftNextLine=function(){var e=getNextLine();var r=getNextLine()||"";return e+r;function getNextLine(){return u=0;r--){this.prepend(e[r])}}else if(e[s]||typeof e==="string"){this.children.unshift(e)}else{throw new TypeError("Expected a SourceNode, string, or an array of SourceNodes and strings. Got "+e)}return this};SourceNode.prototype.walk=function SourceNode_walk(e){var r;for(var n=0,t=this.children.length;n0){r=[];for(n=0;n{function getArg(e,r,n){if(r in e){return e[r]}else if(arguments.length===3){return n}else{throw new Error('"'+r+'" is a required argument.')}}r.getArg=getArg;var n=/^(?:([\w+\-.]+):)?\/\/(?:(\w+:\w+)@)?([\w.-]*)(?::(\d+))?(.*)$/;var t=/^data:.+\,.+$/;function urlParse(e){var r=e.match(n);if(!r){return null}return{scheme:r[1],auth:r[2],host:r[3],port:r[4],path:r[5]}}r.urlParse=urlParse;function urlGenerate(e){var r="";if(e.scheme){r+=e.scheme+":"}r+="//";if(e.auth){r+=e.auth+"@"}if(e.host){r+=e.host}if(e.port){r+=":"+e.port}if(e.path){r+=e.path}return r}r.urlGenerate=urlGenerate;function normalize(e){var n=e;var t=urlParse(e);if(t){if(!t.path){return e}n=t.path}var o=r.isAbsolute(n);var i=n.split(/\/+/);for(var a,u=0,s=i.length-1;s>=0;s--){a=i[s];if(a==="."){i.splice(s,1)}else if(a===".."){u++}else if(u>0){if(a===""){i.splice(s+1,u);u=0}else{i.splice(s,2);u--}}}n=i.join("/");if(n===""){n=o?"/":"."}if(t){t.path=n;return urlGenerate(t)}return n}r.normalize=normalize;function join(e,r){if(e===""){e="."}if(r===""){r="."}var n=urlParse(r);var o=urlParse(e);if(o){e=o.path||"/"}if(n&&!n.scheme){if(o){n.scheme=o.scheme}return urlGenerate(n)}if(n||r.match(t)){return r}if(o&&!o.host&&!o.path){o.host=r;return urlGenerate(o)}var i=r.charAt(0)==="/"?r:normalize(e.replace(/\/+$/,"")+"/"+r);if(o){o.path=i;return urlGenerate(o)}return i}r.join=join;r.isAbsolute=function(e){return e.charAt(0)==="/"||n.test(e)};function relative(e,r){if(e===""){e="."}e=e.replace(/\/$/,"");var n=0;while(r.indexOf(e+"/")!==0){var t=e.lastIndexOf("/");if(t<0){return r}e=e.slice(0,t);if(e.match(/^([^\/]+:\/)?\/*$/)){return r}++n}return Array(n+1).join("../")+r.substr(e.length+1)}r.relative=relative;var o=function(){var e=Object.create(null);return!("__proto__"in e)}();function identity(e){return e}function toSetString(e){if(isProtoString(e)){return"$"+e}return e}r.toSetString=o?identity:toSetString;function fromSetString(e){if(isProtoString(e)){return e.slice(1)}return e}r.fromSetString=o?identity:fromSetString;function isProtoString(e){if(!e){return false}var r=e.length;if(r<9){return false}if(e.charCodeAt(r-1)!==95||e.charCodeAt(r-2)!==95||e.charCodeAt(r-3)!==111||e.charCodeAt(r-4)!==116||e.charCodeAt(r-5)!==111||e.charCodeAt(r-6)!==114||e.charCodeAt(r-7)!==112||e.charCodeAt(r-8)!==95||e.charCodeAt(r-9)!==95){return false}for(var n=r-10;n>=0;n--){if(e.charCodeAt(n)!==36){return false}}return true}function compareByOriginalPositions(e,r,n){var t=strcmp(e.source,r.source);if(t!==0){return t}t=e.originalLine-r.originalLine;if(t!==0){return t}t=e.originalColumn-r.originalColumn;if(t!==0||n){return t}t=e.generatedColumn-r.generatedColumn;if(t!==0){return t}t=e.generatedLine-r.generatedLine;if(t!==0){return t}return strcmp(e.name,r.name)}r.compareByOriginalPositions=compareByOriginalPositions;function compareByGeneratedPositionsDeflated(e,r,n){var t=e.generatedLine-r.generatedLine;if(t!==0){return t}t=e.generatedColumn-r.generatedColumn;if(t!==0||n){return t}t=strcmp(e.source,r.source);if(t!==0){return t}t=e.originalLine-r.originalLine;if(t!==0){return t}t=e.originalColumn-r.originalColumn;if(t!==0){return t}return strcmp(e.name,r.name)}r.compareByGeneratedPositionsDeflated=compareByGeneratedPositionsDeflated;function strcmp(e,r){if(e===r){return 0}if(e===null){return 1}if(r===null){return-1}if(e>r){return 1}return-1}function compareByGeneratedPositionsInflated(e,r){var n=e.generatedLine-r.generatedLine;if(n!==0){return n}n=e.generatedColumn-r.generatedColumn;if(n!==0){return n}n=strcmp(e.source,r.source);if(n!==0){return n}n=e.originalLine-r.originalLine;if(n!==0){return n}n=e.originalColumn-r.originalColumn;if(n!==0){return n}return strcmp(e.name,r.name)}r.compareByGeneratedPositionsInflated=compareByGeneratedPositionsInflated;function parseSourceMapInput(e){return JSON.parse(e.replace(/^\)]}'[^\n]*\n/,""))}r.parseSourceMapInput=parseSourceMapInput;function computeSourceURL(e,r,n){r=r||"";if(e){if(e[e.length-1]!=="/"&&r[0]!=="/"){e+="/"}r=e+r}if(n){var t=urlParse(n);if(!t){throw new Error("sourceMapURL could not be parsed")}if(t.path){var o=t.path.lastIndexOf("/");if(o>=0){t.path=t.path.substring(0,o+1)}}r=join(urlGenerate(t),r)}return normalize(r)}r.computeSourceURL=computeSourceURL},997:(e,r,n)=>{n(591).h;r.SourceMapConsumer=n(952).SourceMapConsumer;n(351)},284:(e,r,n)=>{e=n.nmd(e);var t=n(997).SourceMapConsumer;var o=n(17);var i;try{i=n(147);if(!i.existsSync||!i.readFileSync){i=null}}catch(e){}var a=n(650);function dynamicRequire(e,r){return e.require(r)}var u=false;var s=false;var l=false;var c="auto";var p={};var f={};var g=/^data:application\/json[^,]+base64,/;var h=[];var d=[];function isInBrowser(){if(c==="browser")return true;if(c==="node")return false;return typeof window!=="undefined"&&typeof XMLHttpRequest==="function"&&!(window.require&&window.module&&window.process&&window.process.type==="renderer")}function hasGlobalProcessEventEmitter(){return typeof process==="object"&&process!==null&&typeof process.on==="function"}function globalProcessVersion(){if(typeof process==="object"&&process!==null){return process.version}else{return""}}function globalProcessStderr(){if(typeof process==="object"&&process!==null){return process.stderr}}function globalProcessExit(e){if(typeof process==="object"&&process!==null&&typeof process.exit==="function"){return process.exit(e)}}function handlerExec(e){return function(r){for(var n=0;n"}var n=this.getLineNumber();if(n!=null){r+=":"+n;var t=this.getColumnNumber();if(t){r+=":"+t}}}var o="";var i=this.getFunctionName();var a=true;var u=this.isConstructor();var s=!(this.isToplevel()||u);if(s){var l=this.getTypeName();if(l==="[object Object]"){l="null"}var c=this.getMethodName();if(i){if(l&&i.indexOf(l)!=0){o+=l+"."}o+=i;if(c&&i.indexOf("."+c)!=i.length-c.length-1){o+=" [as "+c+"]"}}else{o+=l+"."+(c||"")}}else if(u){o+="new "+(i||"")}else if(i){o+=i}else{o+=r;a=false}if(a){o+=" ("+r+")"}return o}function cloneCallSite(e){var r={};Object.getOwnPropertyNames(Object.getPrototypeOf(e)).forEach((function(n){r[n]=/^(?:is|get)/.test(n)?function(){return e[n].call(e)}:e[n]}));r.toString=CallSiteToString;return r}function wrapCallSite(e,r){if(r===undefined){r={nextPosition:null,curPosition:null}}if(e.isNative()){r.curPosition=null;return e}var n=e.getFileName()||e.getScriptNameOrSourceURL();if(n){var t=e.getLineNumber();var o=e.getColumnNumber()-1;var i=/^v(10\.1[6-9]|10\.[2-9][0-9]|10\.[0-9]{3,}|1[2-9]\d*|[2-9]\d|\d{3,}|11\.11)/;var a=i.test(globalProcessVersion())?0:62;if(t===1&&o>a&&!isInBrowser()&&!e.isEval()){o-=a}var u=mapSourcePosition({source:n,line:t,column:o});r.curPosition=u;e=cloneCallSite(e);var s=e.getFunctionName;e.getFunctionName=function(){if(r.nextPosition==null){return s()}return r.nextPosition.name||s()};e.getFileName=function(){return u.source};e.getLineNumber=function(){return u.line};e.getColumnNumber=function(){return u.column+1};e.getScriptNameOrSourceURL=function(){return u.source};return e}var l=e.isEval()&&e.getEvalOrigin();if(l){l=mapEvalOrigin(l);e=cloneCallSite(e);e.getEvalOrigin=function(){return l};return e}return e}function prepareStackTrace(e,r){if(l){p={};f={}}var n=e.name||"Error";var t=e.message||"";var o=n+": "+t;var i={nextPosition:null,curPosition:null};var a=[];for(var u=r.length-1;u>=0;u--){a.push("\n at "+wrapCallSite(r[u],i));i.nextPosition=i.curPosition}i.curPosition=i.nextPosition=null;return o+a.reverse().join("")}function getErrorSource(e){var r=/\n at [^(]+ \((.*):(\d+):(\d+)\)/.exec(e.stack);if(r){var n=r[1];var t=+r[2];var o=+r[3];var a=p[n];if(!a&&i&&i.existsSync(n)){try{a=i.readFileSync(n,"utf8")}catch(e){a=""}}if(a){var u=a.split(/(?:\r\n|\r|\n)/)[t-1];if(u){return n+":"+t+"\n"+u+"\n"+new Array(o).join(" ")+"^"}}}return null}function printErrorAndExit(e){var r=getErrorSource(e);var n=globalProcessStderr();if(n&&n._handle&&n._handle.setBlocking){n._handle.setBlocking(true)}if(r){console.error();console.error(r)}console.error(e.stack);globalProcessExit(1)}function shimEmitUncaughtException(){var e=process.emit;process.emit=function(r){if(r==="uncaughtException"){var n=arguments[1]&&arguments[1].stack;var t=this.listeners(r).length>0;if(n&&!t){return printErrorAndExit(arguments[1])}}return e.apply(this,arguments)}}var S=h.slice(0);var _=d.slice(0);r.wrapCallSite=wrapCallSite;r.getErrorSource=getErrorSource;r.mapSourcePosition=mapSourcePosition;r.retrieveSourceMap=v;r.install=function(r){r=r||{};if(r.environment){c=r.environment;if(["node","browser","auto"].indexOf(c)===-1){throw new Error("environment "+c+" was unknown. Available options are {auto, browser, node}")}}if(r.retrieveFile){if(r.overrideRetrieveFile){h.length=0}h.unshift(r.retrieveFile)}if(r.retrieveSourceMap){if(r.overrideRetrieveSourceMap){d.length=0}d.unshift(r.retrieveSourceMap)}if(r.hookRequire&&!isInBrowser()){var n=dynamicRequire(e,"module");var t=n.prototype._compile;if(!t.__sourceMapSupport){n.prototype._compile=function(e,r){p[r]=e;f[r]=undefined;return t.call(this,e,r)};n.prototype._compile.__sourceMapSupport=true}}if(!l){l="emptyCacheBetweenOperations"in r?r.emptyCacheBetweenOperations:false}if(!u){u=true;Error.prepareStackTrace=prepareStackTrace}if(!s){var o="handleUncaughtExceptions"in r?r.handleUncaughtExceptions:true;try{var i=dynamicRequire(e,"worker_threads");if(i.isMainThread===false){o=false}}catch(e){}if(o&&hasGlobalProcessEventEmitter()){s=true;shimEmitUncaughtException()}}};r.resetRetrieveHandlers=function(){h.length=0;d.length=0;h=S.slice(0);d=_.slice(0);v=handlerExec(d);m=handlerExec(h)}},147:e=>{"use strict";e.exports=require("fs")},17:e=>{"use strict";e.exports=require("path")}};var r={};function __webpack_require__(n){var t=r[n];if(t!==undefined){return t.exports}var o=r[n]={id:n,loaded:false,exports:{}};var i=true;try{e[n](o,o.exports,__webpack_require__);i=false}finally{if(i)delete r[n]}o.loaded=true;return o.exports}(()=>{__webpack_require__.nmd=e=>{e.paths=[];if(!e.children)e.children=[];return e}})();if(typeof __webpack_require__!=="undefined")__webpack_require__.ab=__dirname+"/";var n={};(()=>{__webpack_require__(284).install()})();module.exports=n})(); -------------------------------------------------------------------------------- /docs/images/bmc-button.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /docs/images/paypal-button.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 6 | paypal-seeklogo.com 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /jest.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | clearMocks: true, 3 | moduleFileExtensions: ['js', 'ts'], 4 | testMatch: ['**/*.test.ts'], 5 | transform: { 6 | '^.+\\.ts$': 'ts-jest' 7 | }, 8 | verbose: true 9 | } -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "setup-rye", 3 | "version": "4.0.0", 4 | "private": true, 5 | "description": "TypeScript template action", 6 | "main": "dist/index.js", 7 | "scripts": { 8 | "build": "tsc", 9 | "format": "prettier --write '**/*.ts'", 10 | "format-check": "prettier --check '**/*.ts'", 11 | "lint": "eslint src/**/*.ts --fix", 12 | "package": "ncc build -o dist/setup src/setup-rye.ts --source-map --license licenses.txt && ncc build -o dist/save-cache src/save-cache.ts --source-map && ncc build -o dist/update-default-version src/update-default-version.ts --source-map", 13 | "test": "jest", 14 | "act": "act pull_request -W .github/workflows/test.yml --container-architecture linux/amd64 -s GITHUB_TOKEN=\"$(gh auth token)\"", 15 | "all": "npm run build && npm run format && npm run lint && npm run package && npm test" 16 | }, 17 | "repository": { 18 | "type": "git", 19 | "url": "git+https://github.com/actions/typescript-action.git" 20 | }, 21 | "keywords": [ 22 | "actions", 23 | "node", 24 | "setup" 25 | ], 26 | "author": "", 27 | "license": "MIT", 28 | "dependencies": { 29 | "@actions/cache": "^3.2.4", 30 | "@actions/core": "^1.10.1", 31 | "@actions/exec": "^1.1.1", 32 | "@actions/github": "^6.0.0", 33 | "@actions/glob": "^0.4.0", 34 | "@actions/io": "^1.1.3", 35 | "@actions/tool-cache": "^2.0.1", 36 | "@octokit/rest": "^21.0.2" 37 | }, 38 | "devDependencies": { 39 | "@types/node": "^22.10.3", 40 | "@types/semver": "^7.5.8", 41 | "@typescript-eslint/eslint-plugin": "^7.15.0", 42 | "@typescript-eslint/parser": "^7.18.0", 43 | "@vercel/ncc": "^0.38.1", 44 | "eslint": "^8.57.0", 45 | "eslint-plugin-github": "^5.1.4", 46 | "eslint-plugin-import": "^2.29.1", 47 | "eslint-plugin-jest": "^28.6.0", 48 | "eslint-plugin-prettier": "^5.2.1", 49 | "jest": "^29.7.0", 50 | "js-yaml": "^4.1.0", 51 | "prettier": "^3.3.2", 52 | "ts-jest": "^29.1.5", 53 | "typescript": "^5.4.5" 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /src/checksums.ts: -------------------------------------------------------------------------------- 1 | // AUTOGENERATED_DO_NOT_EDIT 2 | export const KNOWN_CHECKSUMS: {[key: string]: string} = { 3 | 'aarch64-linux-0.44.0': 4 | 'c422682e3cbfd78435e1d188cc07453e6f70cd7251222fb0ec23ed63cb0f6957', 5 | 'aarch64-macos-0.44.0': 6 | 'af9e5d09fd839d1f6d49df856a2533d9407b3659ac48cdfbca383320ef0c6801', 7 | 'x86-windows-0.44.0': 8 | '12c08e74a69f8fef1ee4bb80c92994f7d906049451ffe4a9a2548565ed282c75', 9 | 'x86_64-linux-0.44.0': 10 | 'e55e8b844c44820b540c3df46c8d4a3cee43a42ce5302e92bcd99b21d194a9bc', 11 | 'x86_64-macos-0.44.0': 12 | '8529a83e0d83368d466862564f529e3d020c777a4861ec189f9a11d9ff60826a', 13 | 'x86_64-windows-0.44.0': 14 | 'f48d3f3e4eddcaf39c4665e7953e177589006e8ed86772ce782f2b1c4ffb4c0f', 15 | 'aarch64-linux-0.43.0': 16 | '72db8238de446f300a1a9eb9d76caa05a8429aeb3315ae5de606462b9da20c5a', 17 | 'aarch64-macos-0.43.0': 18 | 'ed2be1057853fa584a9a92c643e358805be364e9adcbc86b210d0ac94348325c', 19 | 'x86-windows-0.43.0': 20 | '2c2a4435c9c80a3d4b59aab018cc94eb9838519310916f7fac27538d84722133', 21 | 'x86_64-linux-0.43.0': 22 | 'ca702c3d93fd6ec76a1a0efaaa605e10736ee79a0674d241aad1bc0fe26f7d80', 23 | 'x86_64-macos-0.43.0': 24 | 'eaf3ac78f6dc6b3ccae5ddc9e8e5d54846f864028585440c4ee56453e849eb46', 25 | 'x86_64-windows-0.43.0': 26 | '1c629d4103402fc1e6d9e00ea3243d39aeb7fdec916598c9ce9b595d0b151dd2', 27 | 'aarch64-linux-0.42.0': 28 | '6a57fdcbe2ce946d841b7262652b16be62384efa53b9ef11b8d4c1d1d2e288f4', 29 | 'aarch64-macos-0.42.0': 30 | '592dc9300172c7227a526ebbba66363722d7ac7782d4ca2dd3ac759a99681fd4', 31 | 'x86-windows-0.42.0': 32 | 'e89962127a54ef261fcb22cf8b365a768d9a42954e12f71830d07fa04f4fe3d2', 33 | 'x86_64-linux-0.42.0': 34 | '1233f41f951d1122c1ffed3dbe7b0b101793ddf0d3df635adcf7bd757ac7ccbc', 35 | 'x86_64-macos-0.42.0': 36 | '5794b9e7f09b55ad9471fdd602364b1c8a57aa5d78a74e8034317b38b296597b', 37 | 'x86_64-windows-0.42.0': 38 | 'dd4717831dff0aaa94d492adf4cdbf449d501ad012b0b95b6f525e3d9d62cd10', 39 | 'aarch64-linux-0.41.0': 40 | '2e552844646428120919e6cc698cdeb28f5fe17903f6b4e963bae98474c24d63', 41 | 'aarch64-macos-0.41.0': 42 | '0751aa1f6d82921d44fe3503aab2975f4a52f4ea589f2533a0172d66f31cb243', 43 | 'x86-windows-0.41.0': 44 | 'dafa07263346bc7abe0d3959769745f17877f420cc4f9db777b7a4b35eef1f52', 45 | 'x86_64-linux-0.41.0': 46 | 'db3b57fe48c0704b537c0d1e7028d15d06d5357271d96c8cd8b5fa98cffc7b46', 47 | 'x86_64-macos-0.41.0': 48 | '970962d3391849a649ea2d7325a0149a448c259ff30aaec8c0ca57574f1302a0', 49 | 'x86_64-windows-0.41.0': 50 | '8c78063a8c655c95f1c0f5c7fc4bfb9f3f863f84ab07199af1cd4c1d25a40ddc', 51 | 'aarch64-linux-0.40.0': 52 | '14dd41b1112ab73819333bc5bd51e67eeb5d45fa5b1fa924ce18ef8502dd4530', 53 | 'aarch64-macos-0.40.0': 54 | '38ca66c8efa1e88fb01e815bd11181d5cf45cf91363a366fa1f0b8171c72045d', 55 | 'x86-windows-0.40.0': 56 | '2e1b400456cde2a5d118e4ec162c70d46f651b46e656d7ad0a16b32b7d15ef00', 57 | 'x86_64-linux-0.40.0': 58 | '93c34835187659e1a18f636e9440d47bee7c45b8e6aef5fd95ef6099c20d804e', 59 | 'x86_64-macos-0.40.0': 60 | 'e9689aede59346f543dfbcdefaf077a0a9583bb86b8fb66a2b4ba946fbcb607a', 61 | 'x86_64-windows-0.40.0': 62 | '901909b2d04bbb5df61290d985404a458fa76ddcba44fc6fb2c0d52f6282304f', 63 | 'aarch64-linux-0.39.0': 64 | 'b0a14141f0e24f7138040291bb7151babd1feabbc86c8d4470d5f87f28cbbb1e', 65 | 'aarch64-macos-0.39.0': 66 | 'cb07b89cf481210c6aeb18e7c70369c30b8e74b2e85f80ab4da2acbba78e876f', 67 | 'x86-windows-0.39.0': 68 | 'cf70ad3a6ebc2e93c1abc46ef203b40f1e18113102ab69facefcfb7476269307', 69 | 'x86_64-linux-0.39.0': 70 | '027b4c8170b347986d431d7d960403527f4972d50dcebd64c8d7a3ca6fba7572', 71 | 'x86_64-macos-0.39.0': 72 | 'a5c43cb219ff84181e4795a32acae75dec28f2364c25f59e4d2ea64065db0822', 73 | 'x86_64-windows-0.39.0': 74 | '9a23651934f0228f7d7d4f369e093fd7a12c388c55acfba738e15f38b1d4c418', 75 | 'aarch64-linux-0.38.0': 76 | '5717ecd90d5639886a2d19c1db1eef1b0fb8470109dce55a875c316d098e74e8', 77 | 'aarch64-macos-0.38.0': 78 | '9e093600d959d938731997bbbc98dab419a7a75a09c6badf2675b5c71ae22b5c', 79 | 'x86-windows-0.38.0': 80 | '824b940f4098647f130fd3753bc04b2f14a627eea6add4237d994e41b241cd27', 81 | 'x86_64-linux-0.38.0': 82 | 'a3cc08ae1dc20881dab290b776a7061b3e6d391f4a80926452556d8e66692ec7', 83 | 'x86_64-macos-0.38.0': 84 | '70e0371bc9ad4baf02358a89d200211b292b0ef46faea0826766aec813a549f7', 85 | 'x86_64-windows-0.38.0': 86 | '69af841c5c5f805d02d4f006e448230c4a1f6d0778234340c51ec6b88ccce0e8', 87 | 'aarch64-linux-0.37.0': 88 | 'dccd60a5e1c52aab2c0861c8cd8ca3f43ca3de14e6255062b59498c6c692da5a', 89 | 'aarch64-macos-0.37.0': 90 | 'a1107c3440c705b547d379290ba54f5b7cdf997533888fe0ec2346bc24d0b6c6', 91 | 'x86-windows-0.37.0': 92 | '045a97a7bea78d4601a6e96e176aff7b4f3c674241d636d61e3950531bd5d955', 93 | 'x86_64-linux-0.37.0': 94 | 'fc7c150acc844fd86d709de1428ca96b585f8340edebc5b537ee9fa231f40884', 95 | 'x86_64-macos-0.37.0': 96 | '51798eb078e528aae4a56cc2eff4c45606c1c5f73b84293b45fd5d9347465f4b', 97 | 'x86_64-windows-0.37.0': 98 | '28002a01e4c9e6979079a3eef4cca5c45a0dec90c646cfef6695efdc8706d9cb', 99 | 'aarch64-linux-0.36.0': 100 | '4a26b4aa4eb774fec378f8b1c8eda1cc98fcb8c0347cf557540b73aeb0ec740f', 101 | 'aarch64-macos-0.36.0': 102 | 'd1e2163abc148d1683f3235c916e0725a95b5b9cc250998e4994988b3ccac4b7', 103 | 'x86-windows-0.36.0': 104 | '384a8f1919889e9574a3e54c61c064bdcdb3784f40f66681d7b5cbd681e1be9e', 105 | 'x86_64-linux-0.36.0': 106 | '9be13e1ac28d9ddc602b33ff3e73e9ffd983918538a6195bcdc696a401fa941c', 107 | 'x86_64-macos-0.36.0': 108 | 'a9687fd5610277477e4a847083e724bcf436c806bc5281bca800223c94294972', 109 | 'x86_64-windows-0.36.0': 110 | '809e6986c665e7ef9f669c713616d24f20d434c3ed0c87c009d3f75376060556', 111 | 'aarch64-linux-0.35.0': 112 | 'cf50fe527c37a925cfa3831a114b2148e30d4a01c43db58e0db92f0311ea173f', 113 | 'aarch64-macos-0.35.0': 114 | 'a5ba88beaea78046a0bdafc01dc1ece790c25e8436a27fb265deb2a7a5e9c93d', 115 | 'x86-windows-0.35.0': 116 | '5c7c2e9cc90608c9b42c0050d5c813a5361cdae5e2cba910aa6de04e12aee701', 117 | 'x86_64-linux-0.35.0': 118 | '446cc0e56f1e34823c5eaf2be9e48bc28106ff748a97cd259fcbb01235fcdaf5', 119 | 'x86_64-macos-0.35.0': 120 | '5a21b0078b83a5da6cfad51f29c7a98569d0b5b531653e0523efbfd9cdd3c816', 121 | 'x86_64-windows-0.35.0': 122 | '5ce76d2d3cd7d5c2cee8488d2b75c90f6650aeaacaf66997e871b38228148307', 123 | 'aarch64-linux-0.34.0': 124 | 'a36e4a51f789c1c78e32ee22527ca59682bbac0b74b7c572b81f028498ff56cf', 125 | 'aarch64-macos-0.34.0': 126 | '000a059641df7fea72ef500991311faae03b4b9d5d4d060b79e6559a3ff03f8e', 127 | 'x86-windows-0.34.0': 128 | '59c8c2f986f311a1ba362d09588c545b4a48f4593157ea6003601be829a4425e', 129 | 'x86_64-linux-0.34.0': 130 | 'ea78a7776733a5d7b91e65101f96bc8eb3026b7b1a4570ef2266cd4a054fd531', 131 | 'x86_64-macos-0.34.0': 132 | '929831045085dad753e2a58e0ae3e052b1a62e431ffee8ea00c6f525c7b3ee6c', 133 | 'x86_64-windows-0.34.0': 134 | 'd6dd0d5f505060cbc0cff99941365ef3af0b09c62bba2b75ff111f97c47a7554', 135 | 'aarch64-linux-0.33.0': 136 | 'ad01f0b4543fa5a0d95cb968b49c675feec4c030e49d2652d7c66bb71ef9b04b', 137 | 'aarch64-macos-0.33.0': 138 | '44ef201f256a898e27176e4a890ff681a3ed887deadbc7e8585aaf0d7cd65e6c', 139 | 'x86-windows-0.33.0': 140 | '832b8c3a3f898e45ff0e59d610ed0e751557b74c1ae2680b2471182c865f2834', 141 | 'x86_64-linux-0.33.0': 142 | '77188fa863bc746e2d4f2613603eeeb6ebb774045028c4dd52c01600a9f91344', 143 | 'x86_64-macos-0.33.0': 144 | 'e4d5529c65fa4f5f408dde0d2391c75726a69c48a252c25e8673ac407080e51a', 145 | 'x86_64-windows-0.33.0': 146 | 'a372bcb2347db220d8c5f748a89b3012b9daf6159d73835493d3507a070999b3', 147 | 'aarch64-linux-0.32.0': 148 | '6e367f96ac2f2468b6a846ab9bae486fcdf914e5b7093bbca7218f34fcdadb31', 149 | 'aarch64-macos-0.32.0': 150 | '81cbc36fe71397d9cc36366adc807a6dcb9ccdf62303190b7cf55c3a359506e9', 151 | 'x86-windows-0.32.0': 152 | 'e46ae4e7f068d78f9728a88a86de60869d080c79b95a5ea44b2da1a14c028635', 153 | 'x86_64-linux-0.32.0': 154 | 'c917daac1bbdda4115838116f548236ed3c603d1aef649e72f0cd8078aa1097a', 155 | 'x86_64-macos-0.32.0': 156 | 'dc5459e337fb07f7277686b03bcb11d818fd576ae377f742de47e83810dbdc04', 157 | 'x86_64-windows-0.32.0': 158 | '14972f26921e4bd00031d3cdedb1a86f8611aef540b1f581de6e8eac9fe81458', 159 | 'aarch64-linux-0.31.0': 160 | '15c177641e39e018503fa5b45dc008ad66cd558262cd914d8c3ccd08043d9312', 161 | 'aarch64-macos-0.31.0': 162 | '4e0f3fdd522f15b40d2c47a1175dc25e819b3be84edbaf91ad415e52f261b74b', 163 | 'x86-windows-0.31.0': 164 | '0e0d86887263ccb846aa234d63fb1c1d9ad3b7408a3c24ab879a698c9e13f611', 165 | 'x86_64-linux-0.31.0': 166 | '1cc7f7a644234729e598b44de34d489e1713b87286257464f565b2522de7fadf', 167 | 'x86_64-macos-0.31.0': 168 | 'a47e33371191334e79f8fef93cdf503839367560aabd9f525b8a5828f82f41a0', 169 | 'x86_64-windows-0.31.0': 170 | '0ce46696075608be53a400ff85097d5672d00af6c5054f2e2da8757c443b67fa', 171 | 'aarch64-linux-0.30.0': 172 | 'daf3f91b780f1405f828e601a28596ad7d177eee4f460eba32d5fe737cd7680f', 173 | 'aarch64-macos-0.30.0': 174 | '56cada66b3cc3e4b09eb086bcbc61a35d87f15591efe0b8eaea02307aacc3c5b', 175 | 'x86-windows-0.30.0': 176 | 'a0934af5dc320334d2807dceadd34d2339036e294d6c9647b1688e9b114593ef', 177 | 'x86_64-linux-0.30.0': 178 | '9b7038c7f30ddd62a9df887f9bb9da660eb6b200b22e1774529629ce50f04e36', 179 | 'x86_64-macos-0.30.0': 180 | '03669ddb0f482c614b27b0ba555cff4bc44617a39acbea21cd8d5e6b1a025aee', 181 | 'x86_64-windows-0.30.0': 182 | 'dfacc1d6e35ce4797663032ede116444084884073aecaf8f05297d8507dbf550', 183 | 'aarch64-linux-0.29.0': 184 | '5d743d91525c773d8ee148e2e6f1f16770dae539e39568bad3b03ccd69e5abc7', 185 | 'aarch64-macos-0.29.0': 186 | '67127c80582d0a81806de6a32f8527b298439fe425d32abf322a068a7ae64e89', 187 | 'x86-windows-0.29.0': 188 | '427f2f2ea0a6011ab777933381557dda8bfb50067a76a3ca8b187bea41011fd3', 189 | 'x86_64-linux-0.29.0': 190 | 'a950db192c8e814f5889f45bd926c6a9ea6f7323f7bc18a469036c666f6db815', 191 | 'x86_64-macos-0.29.0': 192 | 'f538d63afc930a5c636a54ae7d644d9793ffcee05a1875aed73b9a7fc621f26b', 193 | 'x86_64-windows-0.29.0': 194 | '98b2425c0d54fa9c96c4ef929285ea9b64834ed9e53c876e3934e2a9ba6a874b', 195 | 'aarch64-linux-0.28.0': 196 | '00c3805b1986ae79787388917964bbeee0a1c4adc3dea1ba0060bd9756f0b405', 197 | 'aarch64-macos-0.28.0': 198 | '90511869fbeb28629d81c5345c74e71e3b3e566f947843c58703a2bb599f82ad', 199 | 'x86-windows-0.28.0': 200 | 'a9ec8335157fc3907d033180076ce656038cc52c0718dace2d27290c4c75914d', 201 | 'x86_64-linux-0.28.0': 202 | '7dc1145925cd47d4afc425d61557031e194f3f2b2a4f8921dccb927a962652e2', 203 | 'x86_64-macos-0.28.0': 204 | '4220b75b2823df21e80507233a7e4320c53044a8518ce26018a2da0e037b1703', 205 | 'x86_64-windows-0.28.0': 206 | '9d3517c96449203aa062bbcad0dc5361610e5606800632508ba68dda616d0b06', 207 | 'aarch64-linux-0.27.0': 208 | '2dac67ea4d3bc7313efe456471f2c0a13939e3dc1636361f8632ae33b1820a84', 209 | 'aarch64-macos-0.27.0': 210 | 'fa0ed382558c8db46777e6865a7a998831b620b558d05846a117ea800cfeb30a', 211 | 'x86-windows-0.27.0': 212 | 'dc20300ba7088f476bc05b255ede57cdaf0d8efb0b9d2e27d6a11b8c744ae888', 213 | 'x86_64-linux-0.27.0': 214 | 'a12731f56522b606413cd741c67a9ddc590855a79b0db6302457e1f1740eacf6', 215 | 'x86_64-macos-0.27.0': 216 | '9da191b434541ba4c9d1c1c881909bddaa8326be70922e81bec5341d57381de9', 217 | 'x86_64-windows-0.27.0': 218 | '91c8ad66d362b754c982d08f1d536f55bdded15a1177a01913916afec0d35e6e', 219 | 'aarch64-linux-0.26.0': 220 | '5da3513279bc3c6491742a350c64e0f1b0f9e0dcd3a5724348862801ee1f603f', 221 | 'aarch64-macos-0.26.0': 222 | 'cc8aae839c20b0f38d5fa9d70d07c7dca5321e6c265a881abef8f7200d197f12', 223 | 'x86-windows-0.26.0': 224 | '53a8e6c3b2cd17759d887b00313bbb0ba992002bc1e13379684f8b74b42a0381', 225 | 'x86_64-linux-0.26.0': 226 | '6f1b95cf68c67f38c78b58728ab209bb2e4ab857b829b738a77b4c2599e074e5', 227 | 'x86_64-macos-0.26.0': 228 | 'f88cc7a8e6cca749c66486a5dc5b3403b1f59da9e6026df4fc70be742db761c3', 229 | 'x86_64-windows-0.26.0': 230 | 'ef199a37c6908cebb7d2b733a17db49509cb45c989eaf682fff030fd5060e8a5', 231 | 'aarch64-linux-0.25.0': 232 | 'df58c4ec62d88c44ce64d27f1eb3690861cee321e9ec12e24cfa0ba39d827689', 233 | 'aarch64-macos-0.25.0': 234 | '4f34bf3a71a362bcbe9ac16c7c701990bfcfc7088d6689f89443374a1e48ba1c', 235 | 'x86-windows-0.25.0': 236 | '0c337a2454ca5b40c01d1d2f82d98cef71d0199bbe1c62b0e4ef8a73e013335a', 237 | 'x86_64-linux-0.25.0': 238 | 'f83aa17df98edd48c950b75cd470ac5892cc30ad205f84c26768be0d1189ceb7', 239 | 'x86_64-macos-0.25.0': 240 | '9861dd0c7d0c187b959d1afcda4826502a4c0bba7a42523fc78114c9125102ba', 241 | 'x86_64-windows-0.25.0': 242 | 'e8430de0747bd0877013d4409c770df6fde73ecfd6565a52cc83dd1d0ec16a82', 243 | 'aarch64-linux-0.24.0': 244 | '497206dbdd305dda61e74e7f11d3f26d0d6790d1e9200a39eac5be00e876c95f', 245 | 'aarch64-macos-0.24.0': 246 | '179e48ee1b236125cc64225cb35885424aa858ed1a297143bcfe586e82c13f70', 247 | 'x86-windows-0.24.0': 248 | '0e5233315c24194087e78f876e1eb818e2899f4b4820e3269196d14ae6024ac7', 249 | 'x86_64-linux-0.24.0': 250 | 'e60ffb6dbc265ab4b0d0e4f38d9df5baa594bc7e55e687ef4737a7f0878de78e', 251 | 'x86_64-macos-0.24.0': 252 | '76b8521333f0deccdcf31d42916c6ac90eb6b5e7214da582ab832ad1d32803ee', 253 | 'x86_64-windows-0.24.0': 254 | 'e7759ce51510228be6635399d4824b3eb9b6d98dd85731a70ce0b44a3ff95ae0', 255 | 'aarch64-linux-0.23.0': 256 | '204d41c8d093358e3205921c59b637b0163356a4628b818134c1c30fd2e82302', 257 | 'aarch64-macos-0.23.0': 258 | 'e9f0d21bfae75c4089303e3a4c95fa277675c0962fa8b24fff0b69418ffd03b2', 259 | 'x86-windows-0.23.0': 260 | 'f3e1c966dfac73531904c01615e686d6b7d6c07b6c5c139699b1431028e37727', 261 | 'x86_64-linux-0.23.0': 262 | '0018fce5a7b185143287cb5fb88d292941b5e760714d1f8a6c0c35d31438fa65', 263 | 'x86_64-macos-0.23.0': 264 | 'b84c4dab08d3e192fa147c73f2a02135c1a0823c55f004b57d926e31036eadbf', 265 | 'x86_64-windows-0.23.0': 266 | 'bd9d763393b40cd61a9d11d571b22ad0ba6c85d5e492785e8245b27a15520d11', 267 | 'aarch64-linux-0.22.0': 268 | 'c6ecec4d5c05524de6b99e877e11475081354049e36d9b1a47c438532e117d48', 269 | 'aarch64-macos-0.22.0': 270 | 'b63b15d82d2c03e05277498607ced2e019e02fbcac399ad1e11179142ad8e87c', 271 | 'x86-windows-0.22.0': 272 | '53f4a7cf41a1c3f936404e87efae0b1a3134cd40699de95bd22666564a66b371', 273 | 'x86_64-linux-0.22.0': 274 | '7400415b9fe2be349e047eb896689c4603c1ca021053f68ebc9f13b10495b2ab', 275 | 'x86_64-macos-0.22.0': 276 | '57b5c5a910b4977b8ae2ffa03dc18500d930b2ecb950aff507e4b7b18e60d744', 277 | 'x86_64-windows-0.22.0': 278 | '20257d23813f646ae4829f822a675f505fd20b73adece4522219f978594a4379', 279 | 'aarch64-linux-0.21.0': 280 | '52bfbb432733f7d93340d92fb245989669d0b2d5f26ad796af5a5198291e0529', 281 | 'aarch64-macos-0.21.0': 282 | '91659e8b2c6fb39ebf2df6220ae10efdec2f85dd8dbfa3023e5f2bf5b491198d', 283 | 'x86-windows-0.21.0': 284 | 'cc870e1eaeea610ed8eb2b35dd79ff7d12faf8ade9419a498119918d836f7149', 285 | 'x86_64-linux-0.21.0': 286 | '41d515170e021e20f72a8dd3ac2404be0681832498a8034aefe3cf59600b39f2', 287 | 'x86_64-macos-0.21.0': 288 | '556cd7b2beccc1410cb4d28b0e6779266e3b40477f1a1ea798c64b46366ae54d', 289 | 'x86_64-windows-0.21.0': 290 | 'a79d95d24519b1375ebd675f2bfad215546943d1d2e7f0713d197396dea6df67', 291 | 'aarch64-linux-0.20.0': 292 | '8ee66241f6696408b30f1eea452a8140d27f50292be4dfd00a1307090490e6e9', 293 | 'aarch64-macos-0.20.0': 294 | '14fcb7ecda0b7c71e2f9496651a5409d0e8c3b8ecc4dcfc96ae1390f40fcf819', 295 | 'x86-windows-0.20.0': 296 | '84ea48643e761f776546c953774c970624bc4f9281e73d4f9e88e0e900687278', 297 | 'x86_64-linux-0.20.0': 298 | 'efb930c2f3350661b6fafe8e7f61a3576f635d217f2262d00a89ed46b64f7999', 299 | 'x86_64-macos-0.20.0': 300 | 'ef12e762b1a1a5c36bee985edd85677c89bb5bf42376370f7b3a53a647e3b4d2', 301 | 'x86_64-windows-0.20.0': 302 | '1824dbaea0943ac3656593daf39cf92cb4b2e142ec60a78f092d6f0605eee2e5', 303 | 'aarch64-linux-0.19.0': 304 | '1b071990b2d709c954be8dac4e9ad4f1bcefad4187e3df34a16dff5ed885d925', 305 | 'aarch64-macos-0.19.0': 306 | '994a345136b2ce19affc3ffd75e35e90c08cc8d4fc76eebdb704b0d4fb644eba', 307 | 'x86-windows-0.19.0': 308 | 'eea52596235d5538527355570e74d2fff074c406322b28be88f7809dc223eeee', 309 | 'x86_64-linux-0.19.0': 310 | 'b1cdb5489556e7ddc9d76206a03e85eda81c1c291a53ea4ac596646f0b35e0da', 311 | 'x86_64-macos-0.19.0': 312 | '02b6a1b0dac8bfc9eb63b2b0667a2856eb99d7fecead599d63db1276fd51fe7b', 313 | 'x86_64-windows-0.19.0': 314 | '81f48f4b9e6dfc5952af368c32bdb92d0dc46c08e11babb2e9ca99fd5b01a33a', 315 | 'aarch64-linux-0.18.0': 316 | '7c74bfaf9befb4d8fda6966238b22c5d613693880094e33d176dd3e85827962f', 317 | 'aarch64-macos-0.18.0': 318 | 'df431f9318f2c2a5af4b470dd98502d79c6b39eab096198c9a30022d59d641f7', 319 | 'x86-windows-0.18.0': 320 | '08fae09ecdee51e092ccd6ce3e0e4ef56b337525b2ccdf796e5dc02eb8cc06b3', 321 | 'x86_64-linux-0.18.0': 322 | '42e7952444697fd36fcaca5af50b3731cda2bfb116ebacf69587f46833fdd246', 323 | 'x86_64-macos-0.18.0': 324 | '69c55e68cd60b5ff7fbcedb57c555fd2fb506201a97e77a97aeadc6409e21bee', 325 | 'x86_64-windows-0.18.0': 326 | '4e38b24abdad9ca4cce93a79ab1dbc5821451cc3e7cc00a4d756e3e61a25fad5', 327 | 'aarch64-linux-0.17.0': 328 | '61d3f2b281d3e5f8a43eb24dd03fb32a8692ba3b2c22802e8d4052a53408b21c', 329 | 'aarch64-macos-0.17.0': 330 | '8b5b7bfb2653d9ae2e397938c4c7ec45426154d5dfccf650a5cfe78073c979c6', 331 | 'x86-windows-0.17.0': 332 | 'f509b153bd92b92f1979bc452f9a174dee9ee0681ef73f71b918dd28f424e0cd', 333 | 'x86_64-linux-0.17.0': 334 | '92a3f3727ea71c524a8a193fdc3bce6cc0588baf4510170423188ec8c4df23b1', 335 | 'x86_64-macos-0.17.0': 336 | 'f25c47662d3c6dd606a35fee631a3755e71939048755782ea584e2fe1eda59b9', 337 | 'x86_64-windows-0.17.0': 338 | '8980175c67413f8a458a5b9c84afde8bbbdfbadb035894a28a0005c66464e7ae', 339 | 'aarch64-linux-0.16.0': 340 | 'b22de221a74179aafa4826d1f6b94fc2c67e886382e08e676c1cadd7a81656ef', 341 | 'aarch64-macos-0.16.0': 342 | 'eadf43cea2c56dfd7206ccdef3316d7716d1d154c60a524425bc2a3f4eb1c2ac', 343 | 'x86-windows-0.16.0': 344 | '128f8dc1465d0f454efae14ca0b9554c2902242669d4ec66b2525fbb4401cca0', 345 | 'x86_64-linux-0.16.0': 346 | 'c1b1f0cf41801b10348074e7da1215ba95eadf1a45cad5a1345a5c70e2f183dd', 347 | 'x86_64-macos-0.16.0': 348 | '60785f384d33135f6193b3255bf69ee2fbf2a25f7a65760e5ab74c77047745bb', 349 | 'x86_64-windows-0.16.0': 350 | '0b8df5fda71ad88bdf69a3d0241156a0d7fa9b29a01e7eab68e16b1a760c5c35', 351 | 'aarch64-linux-0.15.2': 352 | '42130f8ed85668cf42be71880c21c7b44068360acc2a4fc20833821c389ba806', 353 | 'aarch64-macos-0.15.2': 354 | 'f40373e757abf2ac2bcd5ad3e6b05bd9e8da0a47f30e10e4503f4908a32f5063', 355 | 'x86-windows-0.15.2': 356 | 'a494db45bc5e4d02b39be81d9c093cb0bb97cdced24fa041f37641db7a344e52', 357 | 'x86_64-linux-0.15.2': 358 | 'e649a4c95f459669023b78aba934fde6d98f2be646108070a23b7a5f651d7a01', 359 | 'x86_64-macos-0.15.2': 360 | 'f3284498077c10c367c35ab2ea0c19f6e9f75d97a51eff633b9479203f0791be', 361 | 'x86_64-windows-0.15.2': 362 | '4e57a8b9856550d30c7fcba5b7a43abea68996e59f4cfb568e5f617cf9aad657', 363 | 'aarch64-linux-0.15.1': 364 | 'bfde03a365a34a706e12a6183f0736fa3ff987e430be8356129b990c0458cbed', 365 | 'aarch64-macos-0.15.1': 366 | 'ae46af38c4416f15d521062e89259d748909e8221453c1c0c2528e2c78450ffb', 367 | 'x86-windows-0.15.1': 368 | '7d25c0e0422adac9bde8fa875a01b01a399096d667f193244ca07251d9bf33b5', 369 | 'x86_64-linux-0.15.1': 370 | '4bcf59f54e1aeaf50d129f9fe80f3ab598eda3d33c24d0bdec51192eaeac61b9', 371 | 'x86_64-macos-0.15.1': 372 | 'd21958e45ca024a84281c9f3c415c1f9fd4150f6a2e0ee22a26c6da4967eba60', 373 | 'x86_64-windows-0.15.1': 374 | 'fb199d7dc21adba15f799e11e91513dc30a84ea3f2f6c6327c53d8561a3ebc08', 375 | 'aarch64-linux-0.15.0': 376 | '7975c69cddad29324d5123d541d587669e61a365bf310bfcc69404ce7038de1e', 377 | 'aarch64-macos-0.15.0': 378 | '0598a95f91e155d37d905afb55d0f23625f0cf3efcbb4d3dd5c312224be98919', 379 | 'x86-windows-0.15.0': 380 | 'b9bd27b7190eee1968be608f714a2f9d24737eb34da02cf48a10c4687be1c5e3', 381 | 'x86_64-linux-0.15.0': 382 | '8a0f202b3cf8706af331ec439e960503da30d74475ad23631526b9486563a0a2', 383 | 'x86_64-macos-0.15.0': 384 | 'd6ba7e02dbeb9501ca51d877041ee99c09f2726c483dbb400fe7041347743e9a', 385 | 'x86_64-windows-0.15.0': 386 | '69eaf27ce69bba897b5f9f1a84cce1249e1a9ac2d80ec7dc3a791fe9302d95a1', 387 | 'aarch64-linux-0.14.0': 388 | 'eff31fe41152dcb0c43079f33e7c35fd4320c30928fa26ba44deef6583f27522', 389 | 'aarch64-macos-0.14.0': 390 | 'b19ff68bb63208e776f9002e23b548fcc605b215ca90a3847632ee9d28309e1c', 391 | 'x86-windows-0.14.0': 392 | '6e2925f9c434458009d7dcccc36bf0a06ae009f51baf741713446bde80f985c4', 393 | 'x86_64-linux-0.14.0': 394 | '007c01b1efa70f7d7d8d99f1705173dfbbf2427eef65e22c2fbe69c89ea3ca98', 395 | 'x86_64-macos-0.14.0': 396 | '69949dd5c5e7acf951e5582548ba2d19321538667ec2c256cbbb69d14734d0f2', 397 | 'x86_64-windows-0.14.0': 398 | 'e3cb44ba8ce62de81ed90e35219cb96261523c55ab146a31ae1929e6463e8447', 399 | 'aarch64-linux-0.13.0': 400 | 'f09e4f0cc9114a1bc8b5f39f45fe7f20bb2c1b1a416afe4fdba02c5295f0d7df', 401 | 'aarch64-macos-0.13.0': 402 | 'e082822e44dceee8a535690cca76643c1428c41bc492cbe7160a873a66c4a3e5', 403 | 'x86-windows-0.13.0': 404 | 'f89ade3e9362741b02c245436e49908518c1f92677e33f366b47cdb000942a4e', 405 | 'x86_64-linux-0.13.0': 406 | '07daa41c993594c3aeed4eff59974d01d10949f6a51bcdd1f8ada2866d87f795', 407 | 'x86_64-macos-0.13.0': 408 | '921335016f8e74cad9918d67ec4f721c360bfff9ccb76c77959e1b295f4c9c8b', 409 | 'x86_64-windows-0.13.0': 410 | '749a8caa46e834527af4527825e0d829dfe758486963e038f27b3c00c5a75641', 411 | 'aarch64-linux-0.12.0': 412 | 'dfc209bb35213b82b7dbe0784a60184fe3263e204a90da9f1bf672aacbbbdce1', 413 | 'aarch64-macos-0.12.0': 414 | '01cd35aed836c4dc10841c3a622b3398354a0b124df1a59eefe60bd0296533cd', 415 | 'x86-windows-0.12.0': 416 | 'be48999d3c073405765f19064dd273e54ae529e81f31f81b3faa689a70974149', 417 | 'x86_64-linux-0.12.0': 418 | 'c48d850e90649d868d512f60af67c74aa844d80f951fdb38589220662e709da7', 419 | 'x86_64-macos-0.12.0': 420 | '2b36b6d17218983a4c6f53c09ae45f1088525d289c8b5b6703b9081f771ad653', 421 | 'x86_64-windows-0.12.0': 422 | '3dfae62b3f42ff89cbbe3c61582a871db034fb8a8c504b107a4e3613f9d18be4', 423 | 'aarch64-linux-0.11.0': 424 | '7e0b1f6e3490a79c1d2600e8c04dd9ed4ea04d29d6c80f1f5a84a79736e9a21d', 425 | 'aarch64-macos-0.11.0': 426 | '3297df4f538e70e766049ab6a9e426524d76a80460f7e9e01a6d13c471aaf932', 427 | 'x86-windows-0.11.0': 428 | '533a9589b66cbd2bb71391fa7f60364ba3d009694778cee0fe948026278ed973', 429 | 'x86_64-linux-0.11.0': 430 | '00e795573477a2fe2b3c0ac748240364c3369218d314d1df47d2653764e9bfb1', 431 | 'x86_64-macos-0.11.0': 432 | '0e0f76b43b02c04f2159df75a4e0e39e6642d50efed4a4f0d6d7d3ca42d8eb34', 433 | 'x86_64-windows-0.11.0': 434 | '12d3cb63eec70a767c8a96854828da3e0c9de1d64b7a957486c7a7b502bd7644', 435 | 'aarch64-linux-0.10.0': 436 | '3c8af81f1a62bacb332f5a212e000fdec7b028cde4bb5f65ac47b61cd9f51f19', 437 | 'aarch64-macos-0.10.0': 438 | 'badb6db0fef466088252a570457d9b57a649c96a92388501d5a2d9b878f47e17', 439 | 'x86-windows-0.10.0': 440 | '7cdf2319938d79fabee4cb800f4ced81d4aa87f580274f00116374dcfaf716e7', 441 | 'x86_64-linux-0.10.0': 442 | '8f6db96bbb4c8fead144094fae27ba6499443bf22b7d3362ffcfc8d4ae2d876e', 443 | 'x86_64-macos-0.10.0': 444 | 'fcd5c343ef930846a07364f5e475f2a780151829ee043830b6648d86e578dbd1', 445 | 'x86_64-windows-0.10.0': 446 | 'c0109e8a9ab9cf173a85959d51b6ca3f778c631207f17d4a07e4f6c3948ae156', 447 | 'aarch64-linux-0.9.0': 448 | '3553619a9f9424f4d48a497be99159a7a9198740a736a1f244c4150a8e0b1cf3', 449 | 'aarch64-macos-0.9.0': 450 | '4f492da3e0662705e9021894211b9d1d8ad20cf6f76eee8e81131877e14030f5', 451 | 'x86-windows-0.9.0': 452 | '3558766f67b7581a0f78ea718d421221ae038d8729a4cd7517eccf4fa56d38aa', 453 | 'x86_64-linux-0.9.0': 454 | '31cf14b13522ad54661c50e54686cb043c7cf1199af138cb6158ebfd39e7ab78', 455 | 'x86_64-macos-0.9.0': 456 | 'cbba59a1b38fd31478c8e2069c6ebd886166f6737eeb952684406a565453489d', 457 | 'x86_64-windows-0.9.0': 458 | '10a92563ad05c0cc7e1fd58b12f6a43dadb33513982cc0cb79bb383b28b89d02', 459 | 'aarch64-linux-0.8.0': 460 | '63aacc062f4efde4bf8a150e8a7f6bdb741fbebaa30771d8b1255c80f5a729c1', 461 | 'aarch64-macos-0.8.0': 462 | 'cf65fc60a75fe249b632e53a16dcf20e15ffaef632a482bc6e4cf2821b4f02f7', 463 | 'x86-windows-0.8.0': 464 | '7496e8e6f901143d904b258de322039902de79f7ecb9e733c40332c1649acf03', 465 | 'x86_64-linux-0.8.0': 466 | '3fc5760d7506c35bc23e284facd656ae1679e3d5b86af51c311464015907a1cd', 467 | 'x86_64-macos-0.8.0': 468 | 'fcf7793b9948e9f3999777824011681b62640a308ed5437e6f84c7f0dbf04d1a', 469 | 'x86_64-windows-0.8.0': 470 | '6369ae43b433c22404fc4e4b2218c3b1c524567657d341270c5afd9b67352982', 471 | 'aarch64-linux-0.7.0': 472 | 'cfa27678cb2fdbae3caa6c924dd60d8af0b649fbbc61580b2bf5f593ea6c88f1', 473 | 'aarch64-macos-0.7.0': 474 | 'cc7ddfcf3bb190c457afb7d72fe8ed1a4f6656285b74b510caaafc33cb0e6759', 475 | 'x86-windows-0.7.0': 476 | 'aa992b155fb8a59ee331013d43b92caed2c65779b20d181061a875bf3c779762', 477 | 'x86_64-linux-0.7.0': 478 | '73ebedb995af7a15208ebf4d327c1b7f8ef8792bcf319b90f2ecf3775b14733c', 479 | 'x86_64-macos-0.7.0': 480 | '9b276050420ec525f97707980f6710dd6799cf9a4db5b15dba72028099cf3d96', 481 | 'x86_64-windows-0.7.0': 482 | 'e3a4c8847e70b312ea35cd177297a58f28f54c21f695a7607cc4ac9ee2763932', 483 | 'aarch64-linux-0.6.0': 484 | 'f5e25b27091b5363aa96a07ead0c2cf392d70fb34dfcbd9af427684c1cd42e30', 485 | 'aarch64-macos-0.6.0': 486 | '80dd0af2b63b189375278dc6485b5ccc645b15a75bbc62944765627f799afbab', 487 | 'x86-windows-0.6.0': 488 | '4414e6c1bc5f5e3de2c454f8c1f7d2951b50e34668088651b687772271500a49', 489 | 'x86_64-linux-0.6.0': 490 | 'bcc46559f2eda5f89e100869b3c5f1ac61559c11ff7ec3bade24607c3d646f21', 491 | 'x86_64-macos-0.6.0': 492 | '39aa5678412e57808234a6863dc7bf4d6b9d4c9b3f714d410bd44e12d551beca', 493 | 'x86_64-windows-0.6.0': 494 | '04d168f522af4275201225905c51068ad629ea846cd17ebf058d85a4184bfe95', 495 | 'aarch64-linux-0.5.0': 496 | '67745359a1e23e3c86a3b6c9a783c6ffc6f3988183fcb9bec7559ce994ab3ec7', 497 | 'aarch64-macos-0.5.0': 498 | 'f87d01cbec62bdee7ac6ee640ac27c36b029ef4170476691f138a06029bad188', 499 | 'x86-windows-0.5.0': 500 | 'd357c8c37329c5839a159b516b221c7c49ad003b6f158f414427685ec634bbec', 501 | 'x86_64-linux-0.5.0': 502 | '2582b520a9100faf6bf71556879bdbad5e8e1435a46db89843bbb97e39d1a526', 503 | 'x86_64-macos-0.5.0': 504 | '9ae455c424424cbf2d7f54ffdfdfa70597d4b175d66263456a5fbb696b6c99cc', 505 | 'x86_64-windows-0.5.0': 506 | '124193eccadf3693e6ed5cfc752477cb95d69894522de10e72f03e668421e8e8', 507 | 'aarch64-linux-0.4.0': 508 | '0d874b3f9094011e0151d1b7cc1a0e004be8e6dd791dbc01961dc4bccdee8426', 509 | 'aarch64-macos-0.4.0': 510 | '4927c24c27c2f3801bf1c519f96697f7d11e1f035ece2c3f09eef1e16556bfc7', 511 | 'x86-windows-0.4.0': 512 | '9976405f173f50869575c3984fe03712d971e59c2f166d0f96c684db007c883a', 513 | 'x86_64-linux-0.4.0': 514 | '443232a93b2a79be3591276819706b29437fa743816090e7bd60448397a55eb2', 515 | 'x86_64-macos-0.4.0': 516 | 'be202a5cb8803eb36ab11e826d4515583fdbd25edd6276680e44773125ae27af', 517 | 'x86_64-windows-0.4.0': 518 | '0e2017d5580badd2ec6ad3ae02e022ee0d5f3e8140f62644efaaff9080db747f' 519 | } 520 | -------------------------------------------------------------------------------- /src/download/download-latest.ts: -------------------------------------------------------------------------------- 1 | import * as core from '@actions/core' 2 | import * as tc from '@actions/tool-cache' 3 | import * as io from '@actions/io' 4 | import * as exec from '@actions/exec' 5 | import { 6 | Architecture, 7 | OWNER, 8 | Platform, 9 | REPO, 10 | extract, 11 | validateChecksum 12 | } from '../utils' 13 | 14 | export async function downloadLatest( 15 | platform: Platform, 16 | arch: Architecture, 17 | checkSum: string | undefined, 18 | githubToken: string | undefined 19 | ): Promise<{downloadPath: string; version: string}> { 20 | const binary = `rye-${arch}-${platform}` 21 | let downloadUrl = `https://github.com/${OWNER}/${REPO}/releases/latest/download/${binary}` 22 | if (platform === 'windows') { 23 | downloadUrl += '.exe' 24 | } else { 25 | downloadUrl += '.gz' 26 | } 27 | core.info(`Downloading Rye from "${downloadUrl}" ...`) 28 | 29 | let downloadPath = await tc.downloadTool(downloadUrl, undefined, githubToken) 30 | let pathForValidation: string 31 | if (platform === 'windows') { 32 | // On Windows, the downloaded file is an executable, so we don't need to extract it 33 | // but the file must has a valid extension for an executable file. 34 | await io.mv(downloadPath, `${downloadPath}.exe`) 35 | downloadPath = `${downloadPath}.exe` 36 | pathForValidation = downloadPath 37 | } else { 38 | pathForValidation = `${downloadPath}_for_validation.gz` 39 | await io.cp(downloadPath, pathForValidation) 40 | await extract(downloadPath) 41 | } 42 | const version = await getVersion(downloadPath) 43 | await validateChecksum(checkSum, pathForValidation, arch, platform, version) 44 | 45 | return {downloadPath, version} 46 | } 47 | 48 | async function getVersion(downloadPath: string): Promise { 49 | // Parse the output of `rye --version` to get the version 50 | // The output looks like 51 | // rye 0.27.0 52 | // commit: 0.27.0 (43ee4fce0 2024-02-26) 53 | // platform: macos (aarch64) 54 | // self-python: cpython@3.12 55 | // symlink support: true 56 | // uv enabled: true 57 | 58 | const options: exec.ExecOptions = { 59 | silent: !core.isDebug() 60 | } 61 | const execArgs = ['--version'] 62 | 63 | let version = '' 64 | options.listeners = { 65 | stdout: (data: Buffer) => { 66 | version += data.toString() 67 | } 68 | } 69 | await exec.exec(downloadPath, execArgs, options) 70 | const lines = version.split('\n') 71 | const versionLine = lines[0] 72 | const parts = versionLine.split(' ') 73 | return parts[1] 74 | } 75 | -------------------------------------------------------------------------------- /src/download/download-version.ts: -------------------------------------------------------------------------------- 1 | import * as core from '@actions/core' 2 | import * as tc from '@actions/tool-cache' 3 | import * as io from '@actions/io' 4 | import { 5 | Architecture, 6 | OWNER, 7 | Platform, 8 | REPO, 9 | extract, 10 | toolsCacheName, 11 | validateChecksum 12 | } from '../utils' 13 | 14 | export function tryGetFromCache( 15 | arch: Architecture, 16 | version: string 17 | ): string | undefined { 18 | core.debug(`Trying to get rye from tool cache for ${version}...`) 19 | const cachedVersions = tc.findAllVersions(toolsCacheName, arch) 20 | core.debug(`Cached versions: ${cachedVersions}`) 21 | return tc.find(toolsCacheName, version, arch) 22 | } 23 | 24 | export async function downloadVersion( 25 | platform: Platform, 26 | arch: Architecture, 27 | version: string, 28 | checkSum: string | undefined, 29 | githubToken: string | undefined 30 | ): Promise { 31 | const binary = `rye-${arch}-${platform}` 32 | let downloadUrl = `https://github.com/${OWNER}/${REPO}/releases/download/${version}/${binary}` 33 | if (platform === 'windows') { 34 | downloadUrl += '.exe' 35 | } else { 36 | downloadUrl += '.gz' 37 | } 38 | core.info(`Downloading Rye from "${downloadUrl}" ...`) 39 | 40 | let downloadPath = await tc.downloadTool(downloadUrl, undefined, githubToken) 41 | await validateChecksum(checkSum, downloadPath, arch, platform, version) 42 | 43 | if (platform === 'windows') { 44 | // On Windows, the downloaded file is an executable, so we don't need to extract it 45 | // but the file must has a valid extension for an executable file. 46 | await io.mv(downloadPath, `${downloadPath}.exe`) 47 | downloadPath = `${downloadPath}.exe` 48 | } else { 49 | await extract(downloadPath) 50 | } 51 | return downloadPath 52 | } 53 | -------------------------------------------------------------------------------- /src/restore-cache.ts: -------------------------------------------------------------------------------- 1 | import * as crypto from 'crypto' 2 | import * as cache from '@actions/cache' 3 | import * as glob from '@actions/glob' 4 | import * as core from '@actions/core' 5 | import * as fs from 'fs' 6 | import path from 'path' 7 | import {cp} from '@actions/io/' 8 | import {exists} from '@actions/io/lib/io-util' 9 | import {getArch} from './utils' 10 | 11 | export const STATE_CACHE_KEY = 'cache-key' 12 | export const STATE_CACHE_MATCHED_KEY = 'cache-matched-key' 13 | const workingDirInput = core.getInput('working-directory') 14 | const workingDir = workingDirInput ? `${path.sep}${workingDirInput}` : '' 15 | export const WORKING_DIR_PATH = `${process.env['GITHUB_WORKSPACE']}${workingDir}` 16 | export const VENV_PATH = `${process.env['GITHUB_WORKSPACE']}${workingDir}${path.sep}.venv` 17 | const CACHE_VERSION = '5' 18 | const cacheLocalStoragePath = 19 | `${core.getInput('cache-local-storage-path')}` || '' 20 | const cacheDependencyPath = `${process.env['GITHUB_WORKSPACE']}${workingDir}${path.sep}${path.sep}requirements**.lock` 21 | 22 | export async function restoreCache( 23 | cachePrefix: string, 24 | version: string 25 | ): Promise { 26 | const cacheKey = await computeKeys(cachePrefix, version) 27 | if (cacheKey.endsWith('-')) { 28 | throw new Error( 29 | `No file in ${process.cwd()} matched to [${cacheDependencyPath}], make sure you have checked out the target repository` 30 | ) 31 | } 32 | 33 | let matchedKey: string | undefined 34 | core.info(`Trying to restore .venv from cache with key: ${cacheKey}`) 35 | try { 36 | matchedKey = cacheLocalStoragePath 37 | ? await restoreCacheLocal(cacheKey) 38 | : await cache.restoreCache([VENV_PATH], cacheKey) 39 | } catch (err) { 40 | const message = (err as Error).message 41 | core.warning(message) 42 | core.setOutput('cache-hit', false) 43 | return 44 | } 45 | 46 | core.saveState(STATE_CACHE_KEY, cacheKey) 47 | 48 | handleMatchResult(matchedKey, cacheKey) 49 | } 50 | 51 | async function computeKeys( 52 | cachePrefix: string, 53 | version: string 54 | ): Promise { 55 | const cacheDependencyPathHash = await glob.hashFiles(cacheDependencyPath) 56 | const workingDirHash = workingDir 57 | ? `-${crypto.createHash('sha256').update(workingDir).digest('hex')}` 58 | : '' 59 | const prefix = cachePrefix ? `${cachePrefix}-` : '' 60 | return `${prefix}setup-rye-${CACHE_VERSION}-${process.env['RUNNER_OS']}-${getArch()}-rye-${version}${workingDirHash}-${cacheDependencyPathHash}` 61 | } 62 | 63 | function handleMatchResult( 64 | matchedKey: string | undefined, 65 | primaryKey: string 66 | ): void { 67 | if (!matchedKey) { 68 | core.info( 69 | `No${cacheLocalStoragePath ? ' local' : ''} cache found for key: ${primaryKey}` 70 | ) 71 | core.setOutput('cache-hit', false) 72 | return 73 | } 74 | 75 | const venvPathMatch = doesCachedVenvPathMatchCurrentVenvPath() 76 | if (!venvPathMatch) { 77 | fs.rmSync(VENV_PATH, {recursive: true}) 78 | core.setOutput('cache-hit', false) 79 | return 80 | } 81 | 82 | core.saveState(STATE_CACHE_MATCHED_KEY, matchedKey) 83 | core.info( 84 | `.venv restored from${cacheLocalStoragePath ? ' local' : ''} cache with key: ${matchedKey}` 85 | ) 86 | core.setOutput('cache-hit', true) 87 | } 88 | 89 | function doesCachedVenvPathMatchCurrentVenvPath(): boolean { 90 | const ryeVenvPath = `${VENV_PATH}${path.sep}rye-venv.json` 91 | const ryeVenv = JSON.parse(fs.readFileSync(ryeVenvPath, 'utf8')) 92 | core.info( 93 | `Checking if the cached .venv matches the current path: ${VENV_PATH}` 94 | ) 95 | if (ryeVenv.venv_path !== VENV_PATH) { 96 | core.warning( 97 | `The .venv in the cache cannot be used because it is from another location: ${ryeVenv.venv_path}` 98 | ) 99 | return false 100 | } 101 | return true 102 | } 103 | 104 | async function restoreCacheLocal( 105 | primaryKey: string 106 | ): Promise { 107 | const storedCache = `${cacheLocalStoragePath}${path.sep}${primaryKey}` 108 | if (await exists(storedCache)) { 109 | await cp(`${storedCache}${path.sep}.venv`, VENV_PATH, { 110 | recursive: true 111 | }) 112 | return primaryKey 113 | } 114 | } 115 | -------------------------------------------------------------------------------- /src/save-cache.ts: -------------------------------------------------------------------------------- 1 | import * as cache from '@actions/cache' 2 | import * as core from '@actions/core' 3 | import * as io from '@actions/io/' 4 | import path from 'path' 5 | import { 6 | STATE_CACHE_MATCHED_KEY, 7 | STATE_CACHE_KEY, 8 | VENV_PATH 9 | } from './restore-cache' 10 | 11 | const enableCache = core.getInput('enable-cache') === 'true' 12 | const cacheLocalStoragePath = 13 | `${core.getInput('cache-local-storage-path')}` || '' 14 | 15 | export async function run(): Promise { 16 | try { 17 | if (enableCache) { 18 | await saveCache() 19 | } 20 | } catch (error) { 21 | const err = error as Error 22 | core.setFailed(err.message) 23 | } 24 | process.exit(0) 25 | } 26 | 27 | async function saveCache(): Promise { 28 | const cacheKey = core.getState(STATE_CACHE_KEY) 29 | const matchedKey = core.getState(STATE_CACHE_MATCHED_KEY) 30 | 31 | if (!cacheKey) { 32 | core.warning('Error retrieving cache key from state.') 33 | return 34 | } else if (matchedKey === cacheKey) { 35 | // no change in target directories 36 | core.info(`Cache hit occurred on key ${cacheKey}, not saving .venv.`) 37 | return 38 | } 39 | core.info(`Saving .venv path: ${VENV_PATH}`) 40 | cacheLocalStoragePath 41 | ? await saveCacheLocal(cacheKey) 42 | : await cache.saveCache([VENV_PATH], cacheKey) 43 | 44 | core.info(`.venv saved with the key: ${cacheKey}`) 45 | } 46 | 47 | async function saveCacheLocal(cacheKey: string): Promise { 48 | const targetPath = `${cacheLocalStoragePath}${path.sep}${cacheKey}` 49 | await io.mkdirP(targetPath) 50 | await io.cp(VENV_PATH, `${targetPath}${path.sep}.venv`, { 51 | recursive: true 52 | }) 53 | } 54 | 55 | run() 56 | -------------------------------------------------------------------------------- /src/setup-rye.ts: -------------------------------------------------------------------------------- 1 | import * as core from '@actions/core' 2 | import * as tc from '@actions/tool-cache' 3 | import * as exec from '@actions/exec' 4 | import * as io from '@actions/io' 5 | import * as path from 'path' 6 | import * as fs from 'fs' 7 | import {downloadVersion, tryGetFromCache} from './download/download-version' 8 | import {restoreCache, WORKING_DIR_PATH} from './restore-cache' 9 | import { 10 | Architecture, 11 | EARLIEST_VERSION_WITH_NO_MODIFY_PATHSUPPORT, 12 | VERSIONS_WHICH_MODIFY_PROFILE, 13 | getArch, 14 | compareVersions, 15 | toolsCacheName, 16 | getPlatform, 17 | Platform, 18 | RYE_CONFIG_TOML, 19 | RYE_CONFIG_TOML_BACKUP 20 | } from './utils' 21 | import {downloadLatest} from './download/download-latest' 22 | 23 | async function run(): Promise { 24 | const platform = getPlatform() 25 | const arch = getArch() 26 | const versionInput = core.getInput('version') 27 | const checkSum = core.getInput('checksum') 28 | const enableCache = core.getInput('enable-cache') === 'true' 29 | const cachePrefix = core.getInput('cache-prefix') || '' 30 | const githubToken = core.getInput('github-token') 31 | 32 | try { 33 | if (platform === undefined) { 34 | throw new Error(`Unsupported platform: ${process.platform}`) 35 | } 36 | if (arch === undefined) { 37 | throw new Error(`Unsupported architecture: ${process.arch}`) 38 | } 39 | const setupResult = await setupRye( 40 | platform, 41 | arch, 42 | versionInput, 43 | checkSum, 44 | githubToken 45 | ) 46 | 47 | setVersion(setupResult.version) 48 | addRyeToPath(setupResult.installedPath) 49 | addMatchers() 50 | await ensureCleanConfig(setupResult.installedPath) 51 | 52 | if (enableCache) { 53 | await restoreCache(cachePrefix, setupResult.version) 54 | } 55 | } catch (err) { 56 | core.setFailed((err as Error).message) 57 | } 58 | process.exit(0) 59 | } 60 | 61 | async function setupRye( 62 | platform: Platform, 63 | arch: Architecture, 64 | versionInput: string, 65 | checkSum: string | undefined, 66 | githubToken: string | undefined 67 | ): Promise<{version: string; installedPath: string}> { 68 | let installedPath: string | undefined 69 | let downloadPath: string 70 | let version: string 71 | if (versionInput === 'latest') { 72 | const result = await downloadLatest(platform, arch, checkSum, githubToken) 73 | version = result.version 74 | downloadPath = result.downloadPath 75 | } else { 76 | version = versionInput 77 | installedPath = tryGetFromCache(arch, versionInput) 78 | if (installedPath) { 79 | core.info(`Found Rye in tools-cache for ${versionInput}`) 80 | return {version, installedPath} 81 | } 82 | downloadPath = await downloadVersion( 83 | platform, 84 | arch, 85 | versionInput, 86 | checkSum, 87 | githubToken 88 | ) 89 | } 90 | 91 | installedPath = await installRye(downloadPath, arch, version) 92 | await createConfigBackup(installedPath) 93 | return {version, installedPath} 94 | } 95 | 96 | async function installRye( 97 | downloadPath: string, 98 | arch: string, 99 | version: string 100 | ): Promise { 101 | const tempDir = path.join(process.env['RUNNER_TEMP'] || '', 'rye_temp_home') 102 | await io.mkdirP(tempDir) 103 | core.debug(`Created temporary directory ${tempDir}`) 104 | // Cache first to get the correct path 105 | const cachedPath = await tc.cacheDir(tempDir, toolsCacheName, version, arch) 106 | const toolchainVersion = await determineToolchainVersion() 107 | const env = toolchainVersion 108 | ? { 109 | ...process.env, 110 | RYE_HOME: cachedPath, 111 | RYE_TOOLCHAIN_VERSION: toolchainVersion 112 | } 113 | : {...process.env, RYE_HOME: cachedPath} 114 | const options: exec.ExecOptions = { 115 | cwd: cachedPath, 116 | silent: !core.isDebug(), 117 | env: env 118 | } 119 | core.info(`Installing Rye into ${cachedPath}`) 120 | const execArgs = ['self', 'install', '--yes'] 121 | if ( 122 | compareVersions(version, EARLIEST_VERSION_WITH_NO_MODIFY_PATHSUPPORT) >= 0 123 | ) { 124 | execArgs.push('--no-modify-path') 125 | } 126 | await exec.exec(downloadPath, execArgs, options) 127 | return cachedPath 128 | } 129 | 130 | async function determineToolchainVersion(): Promise { 131 | const supportedMinorVersions = ['9', '10', '11', '12'] 132 | const pythonVersionFile = `${WORKING_DIR_PATH}${path.sep}.python-version` 133 | if (fs.existsSync(pythonVersionFile)) { 134 | const fileContent = await fs.promises.readFile(pythonVersionFile, 'utf8') 135 | const toolchainVersion = fileContent.trim() 136 | if ( 137 | toolchainVersion.startsWith('cpython@3') || 138 | toolchainVersion.startsWith('3') 139 | ) { 140 | const minorVersion = toolchainVersion.split('.')[1] 141 | if (supportedMinorVersions.includes(minorVersion)) { 142 | core.info(`Determined RYE_TOOLCHAIN_VERSION: ${toolchainVersion}`) 143 | return toolchainVersion 144 | } 145 | } 146 | core.warning( 147 | `Unsupported version in .python-version: ${toolchainVersion}, using default RYE_TOOLCHAIN_VERSION` 148 | ) 149 | return 150 | } 151 | core.warning( 152 | `No .python-version file found, using default RYE_TOOLCHAIN_VERSION` 153 | ) 154 | return 155 | } 156 | 157 | async function createConfigBackup(installedPath: string): Promise { 158 | if (fs.existsSync(`${installedPath}${path.sep}${RYE_CONFIG_TOML}`)) { 159 | await io.cp( 160 | `${installedPath}${path.sep}${RYE_CONFIG_TOML}`, 161 | `${installedPath}${path.sep}${RYE_CONFIG_TOML_BACKUP}` 162 | ) 163 | core.info(`Backed up ${installedPath}${path.sep}${RYE_CONFIG_TOML}`) 164 | } 165 | } 166 | 167 | async function ensureCleanConfig(installedPath: string): Promise { 168 | if (fs.existsSync(`${installedPath}${path.sep}${RYE_CONFIG_TOML_BACKUP}`)) { 169 | await io.rmRF(`${installedPath}${path.sep}${RYE_CONFIG_TOML}`) 170 | await io.cp( 171 | `${installedPath}${path.sep}${RYE_CONFIG_TOML_BACKUP}`, 172 | `${installedPath}${path.sep}${RYE_CONFIG_TOML}` 173 | ) 174 | core.info( 175 | `Restored clean ${RYE_CONFIG_TOML} from ${installedPath}${path.sep}${RYE_CONFIG_TOML_BACKUP}` 176 | ) 177 | } 178 | } 179 | 180 | function setVersion(version: string): void { 181 | if (VERSIONS_WHICH_MODIFY_PROFILE.includes(version)) { 182 | core.warning( 183 | `Rye version ${version} adds a wrong path to the file ~/.profile. Consider using version ${EARLIEST_VERSION_WITH_NO_MODIFY_PATHSUPPORT} or later instead.` 184 | ) 185 | } 186 | core.setOutput('rye-version', version) 187 | } 188 | 189 | function addRyeToPath(cachedPath: string): void { 190 | core.addPath(`${cachedPath}${path.sep}shims`) 191 | core.info(`Added ${cachedPath}${path.sep}shims to the path`) 192 | core.exportVariable('RYE_HOME', cachedPath) 193 | core.info(`Set RYE_HOME to ${cachedPath}`) 194 | } 195 | 196 | function addMatchers(): void { 197 | const matchersPath = path.join(__dirname, `..${path.sep}..`, '.github') 198 | core.info(`##[add-matcher]${path.join(matchersPath, 'python.json')}`) 199 | } 200 | 201 | run() 202 | -------------------------------------------------------------------------------- /src/update-default-version.ts: -------------------------------------------------------------------------------- 1 | import * as github from '@actions/github' 2 | import * as core from '@actions/core' 3 | import * as tc from '@actions/tool-cache' 4 | import {OWNER, REPO} from './utils' 5 | import {createReadStream, promises as fs} from 'fs' 6 | import * as readline from 'readline' 7 | import * as semver from 'semver' 8 | 9 | async function run(): Promise { 10 | const checksumFilePath = process.argv.slice(2)[0] 11 | const defaultVersionFilePath = process.argv.slice(2)[1] 12 | const github_token = process.argv.slice(2)[2] 13 | 14 | const octokit = github.getOctokit(github_token) 15 | 16 | const response = await octokit.paginate(octokit.rest.repos.listReleases, { 17 | owner: OWNER, 18 | repo: REPO 19 | }) 20 | const downloadUrls: string[] = response.flatMap(release => 21 | release.assets 22 | .filter(asset => asset.name.endsWith('.sha256')) 23 | .map(asset => asset.browser_download_url) 24 | ) 25 | await updateChecksums(checksumFilePath, downloadUrls) 26 | 27 | const latestVersion = response 28 | .map(release => release.tag_name) 29 | .sort(semver.rcompare)[0] 30 | core.setOutput('latest-version', latestVersion) 31 | await updateDefaultVersion(defaultVersionFilePath, latestVersion) 32 | } 33 | 34 | async function updateChecksums( 35 | filePath: string, 36 | downloadUrls: string[] 37 | ): Promise { 38 | await fs.rm(filePath) 39 | await fs.appendFile( 40 | filePath, 41 | '// AUTOGENERATED_DO_NOT_EDIT\nexport const KNOWN_CHECKSUMS: {[key: string]: string} = {\n' 42 | ) 43 | let firstLine = true 44 | for (const downloadUrl of downloadUrls) { 45 | const content = await downloadAsset(downloadUrl) 46 | const key = getKey(downloadUrl) 47 | if (!firstLine) { 48 | await fs.appendFile(filePath, ',\n') 49 | } 50 | await fs.appendFile(filePath, ` '${key}':\n '${content.trim()}'`) 51 | firstLine = false 52 | } 53 | await fs.appendFile(filePath, '}\n') 54 | } 55 | 56 | async function updateDefaultVersion( 57 | filePath: string, 58 | latestVersion: string 59 | ): Promise { 60 | const fileStream = createReadStream(filePath) 61 | 62 | const rl = readline.createInterface({ 63 | input: fileStream 64 | }) 65 | 66 | let foundDescription = false 67 | const lines = [] 68 | 69 | for await (let line of rl) { 70 | if ( 71 | !foundDescription && 72 | line.includes("description: 'The version of rye to install'") 73 | ) { 74 | foundDescription = true 75 | } else if (foundDescription && line.includes('default: ')) { 76 | line = line.replace(/'[^']*'/, `'${latestVersion}'`) 77 | foundDescription = false 78 | } 79 | lines.push(line) 80 | } 81 | 82 | await fs.writeFile(filePath, lines.join('\n')) 83 | } 84 | 85 | function getKey(downloadUrl: string): string { 86 | // https://github.com/astral-sh/rye/releases/download/0.4.0/rye-x86_64-windows.exe.sha256 87 | const parts = downloadUrl.split('/') 88 | const fileName = parts[parts.length - 1] 89 | const name = fileName.split('.')[0].split('rye-')[1] 90 | const version = parts[parts.length - 2] 91 | return `${name}-${version}` 92 | } 93 | 94 | async function downloadAsset(downloadUrl: string): Promise { 95 | const downloadPath = await tc.downloadTool(downloadUrl) 96 | const content = await fs.readFile(downloadPath, 'utf8') 97 | return content 98 | } 99 | 100 | run() 101 | -------------------------------------------------------------------------------- /src/utils.ts: -------------------------------------------------------------------------------- 1 | import * as fs from 'fs' 2 | import * as crypto from 'crypto' 3 | import * as io from '@actions/io' 4 | import * as core from '@actions/core' 5 | import * as exec from '@actions/exec' 6 | import {KNOWN_CHECKSUMS} from './checksums' 7 | 8 | export const WINDOWS_ARCHS = ['x86', 'x64'] 9 | export const WINDOWS_PLATFORMS = ['win32', 'win64'] 10 | 11 | export const REPO = 'rye' 12 | export const OWNER = 'astral-sh' 13 | 14 | export const toolsCacheName = 'setup-rye-2024-03-04' // Custom name for cache busting 15 | export const RYE_CONFIG_TOML_BACKUP = 'config.toml.bak' 16 | export const RYE_CONFIG_TOML = 'config.toml' 17 | 18 | export const EARLIEST_VERSION_WITH_NO_MODIFY_PATHSUPPORT = '0.25.0' 19 | export const VERSIONS_WHICH_MODIFY_PROFILE = [ 20 | '0.21.0', 21 | '0.22.0', 22 | '0.23.0', 23 | '0.24.0' 24 | ] 25 | 26 | export type Platform = 'linux' | 'macos' | 'windows' 27 | export type Architecture = 'x86' | 'x86_64' | 'aarch64' 28 | 29 | export enum ComparisonResult { 30 | Greater = 1, 31 | Equal = 0, 32 | Less = -1 33 | } 34 | 35 | export async function validateChecksum( 36 | checkSum: string | undefined, 37 | downloadPath: string, 38 | arch: Architecture, 39 | platform: string, 40 | version: string 41 | ): Promise { 42 | let isValid = true 43 | if (checkSum !== undefined && checkSum !== '') { 44 | isValid = await validateFileCheckSum(downloadPath, checkSum) 45 | } else { 46 | core.debug(`Checksum not provided. Checking known checksums.`) 47 | const key = `${arch}-${platform}-${version}` 48 | if (key in KNOWN_CHECKSUMS) { 49 | const knownChecksum = KNOWN_CHECKSUMS[`${arch}-${platform}-${version}`] 50 | core.debug(`Checking checksum for ${arch}-${platform}-${version}.`) 51 | isValid = await validateFileCheckSum(downloadPath, knownChecksum) 52 | } else { 53 | core.debug(`No known checksum found for ${key}.`) 54 | } 55 | } 56 | 57 | if (!isValid) { 58 | throw new Error(`Checksum for ${downloadPath} did not match ${checkSum}.`) 59 | } 60 | core.debug(`Checksum for ${downloadPath} is valid.`) 61 | } 62 | 63 | export async function extract(downloadPath: string): Promise { 64 | core.info('Extracting downloaded archive...') 65 | const pathForGunzip = `${downloadPath}.gz` 66 | await io.mv(downloadPath, pathForGunzip) 67 | await exec.exec('gunzip', [pathForGunzip]) 68 | await exec.exec('chmod', ['+x', downloadPath]) 69 | } 70 | 71 | export function compareVersions( 72 | versionA: string, 73 | versionB: string 74 | ): ComparisonResult { 75 | const versionPartsA = versionA.split('.').map(Number) 76 | const versionPartsB = versionB.split('.').map(Number) 77 | 78 | for (let i = 0; i < versionPartsA.length; i++) { 79 | if (versionPartsA[i] > versionPartsB[i]) { 80 | return ComparisonResult.Greater 81 | } else if (versionPartsA[i] < versionPartsB[i]) { 82 | return ComparisonResult.Less 83 | } 84 | } 85 | return ComparisonResult.Equal 86 | } 87 | 88 | export async function validateFileCheckSum( 89 | filePath: string, 90 | expected: string 91 | ): Promise { 92 | return new Promise((resolve, reject) => { 93 | const hash = crypto.createHash('sha256') 94 | const stream = fs.createReadStream(filePath) 95 | stream.on('error', err => reject(err)) 96 | stream.on('data', chunk => hash.update(chunk)) 97 | stream.on('end', () => { 98 | const actual = hash.digest('hex') 99 | resolve(actual === expected) 100 | }) 101 | }) 102 | } 103 | 104 | export function isknownVersion(version: string): boolean { 105 | const pattern = new RegExp(`^.*-.*-${version}$`) 106 | return Object.keys(KNOWN_CHECKSUMS).some(key => pattern.test(key)) 107 | } 108 | 109 | export function getArch(): Architecture | undefined { 110 | const arch = process.arch 111 | core.debug(`Arch: ${arch}`) 112 | const archMapping: {[key: string]: Architecture} = { 113 | ia32: 'x86', 114 | x64: 'x86_64', 115 | arm64: 'aarch64' 116 | } 117 | 118 | if (arch in archMapping) { 119 | return archMapping[arch] 120 | } 121 | } 122 | 123 | export function getPlatform(): Platform | undefined { 124 | const platform = process.platform 125 | core.debug(`Platform: ${platform}`) 126 | if (platform === 'linux') { 127 | return 'linux' 128 | } else if (platform === 'darwin') { 129 | return 'macos' 130 | } else if (platform === 'win32') { 131 | return 'windows' 132 | } 133 | } 134 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es6", /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', 'ES2018', 'ES2019' or 'ESNEXT'. */ 4 | "module": "commonjs", /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', or 'ESNext'. */ 5 | "outDir": "./lib", /* Redirect output structure to the directory. */ 6 | "rootDir": "./src", /* Specify the root directory of input files. Use to control the output directory structure with --outDir. */ 7 | "strict": true, /* Enable all strict type-checking options. */ 8 | "noImplicitAny": true, /* Raise error on expressions and declarations with an implied 'any' type. */ 9 | "esModuleInterop": true /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */ 10 | }, 11 | "exclude": ["node_modules", "**/*.test.ts"] 12 | } 13 | --------------------------------------------------------------------------------