Full Code of volta-cli/volta for AI

main 5eedd5fb2f68 cached
226 files
1008.4 KB
252.7k tokens
1680 symbols
1 requests
Download .txt
Showing preview only (1,070K chars total). Download the full file or copy to clipboard to get everything.
Repository: volta-cli/volta
Branch: main
Commit: 5eedd5fb2f68
Files: 226
Total size: 1008.4 KB

Directory structure:
gitextract_9r0abwvz/

├── .cargo/
│   └── config.toml
├── .github/
│   ├── dependabot.yml
│   └── workflows/
│       ├── api-docs.yml
│       ├── release.yml
│       └── test.yml
├── .gitignore
├── .vscode/
│   ├── launch.json
│   └── settings.json
├── CODE_OF_CONDUCT.md
├── COMPATIBILITY.md
├── CONTRIBUTING.md
├── Cargo.toml
├── LICENSE
├── README.md
├── RELEASES.md
├── ci/
│   ├── build-linux.sh
│   ├── build-macos.sh
│   ├── docker/
│   │   └── Dockerfile
│   └── volta.manifest
├── crates/
│   ├── archive/
│   │   ├── Cargo.toml
│   │   └── src/
│   │       ├── lib.rs
│   │       ├── tarball.rs
│   │       └── zip.rs
│   ├── fs-utils/
│   │   ├── Cargo.toml
│   │   └── src/
│   │       └── lib.rs
│   ├── progress-read/
│   │   ├── Cargo.toml
│   │   └── src/
│   │       └── lib.rs
│   ├── test-support/
│   │   ├── Cargo.toml
│   │   └── src/
│   │       ├── lib.rs
│   │       ├── matchers.rs
│   │       ├── paths.rs
│   │       └── process.rs
│   ├── validate-npm-package-name/
│   │   ├── Cargo.toml
│   │   └── src/
│   │       └── lib.rs
│   ├── volta-core/
│   │   ├── Cargo.toml
│   │   ├── fixtures/
│   │   │   ├── basic/
│   │   │   │   ├── package.json
│   │   │   │   └── subdir/
│   │   │   │       └── .gitkeep
│   │   │   ├── cycle-1/
│   │   │   │   ├── package.json
│   │   │   │   └── volta.json
│   │   │   ├── cycle-2/
│   │   │   │   ├── package.json
│   │   │   │   ├── workspace-1.json
│   │   │   │   └── workspace-2.json
│   │   │   ├── hooks/
│   │   │   │   ├── bins.json
│   │   │   │   ├── event_url.json
│   │   │   │   ├── format_github.json
│   │   │   │   ├── format_npm.json
│   │   │   │   ├── prefixes.json
│   │   │   │   ├── project/
│   │   │   │   │   ├── .volta/
│   │   │   │   │   │   └── hooks.json
│   │   │   │   │   └── package.json
│   │   │   │   └── templates.json
│   │   │   ├── nested/
│   │   │   │   ├── package.json
│   │   │   │   └── subproject/
│   │   │   │       ├── inner_project/
│   │   │   │       │   └── package.json
│   │   │   │       └── package.json
│   │   │   ├── no_toolchain/
│   │   │   │   └── package.json
│   │   │   └── yarn/
│   │   │       ├── pnp-cjs/
│   │   │       │   ├── .pnp.cjs
│   │   │       │   └── package.json
│   │   │       ├── pnp-js/
│   │   │       │   ├── .pnp.js
│   │   │       │   └── package.json
│   │   │       └── yarnrc-yml/
│   │   │           ├── .yarnrc.yml
│   │   │           └── package.json
│   │   └── src/
│   │       ├── command.rs
│   │       ├── error/
│   │       │   ├── kind.rs
│   │       │   ├── mod.rs
│   │       │   └── reporter.rs
│   │       ├── event.rs
│   │       ├── fs.rs
│   │       ├── hook/
│   │       │   ├── mod.rs
│   │       │   ├── serial.rs
│   │       │   └── tool.rs
│   │       ├── inventory.rs
│   │       ├── layout/
│   │       │   ├── mod.rs
│   │       │   ├── unix.rs
│   │       │   └── windows.rs
│   │       ├── lib.rs
│   │       ├── log.rs
│   │       ├── monitor.rs
│   │       ├── platform/
│   │       │   ├── image.rs
│   │       │   ├── mod.rs
│   │       │   ├── system.rs
│   │       │   └── tests.rs
│   │       ├── project/
│   │       │   ├── mod.rs
│   │       │   ├── serial.rs
│   │       │   └── tests.rs
│   │       ├── run/
│   │       │   ├── binary.rs
│   │       │   ├── executor.rs
│   │       │   ├── mod.rs
│   │       │   ├── node.rs
│   │       │   ├── npm.rs
│   │       │   ├── npx.rs
│   │       │   ├── parser.rs
│   │       │   ├── pnpm.rs
│   │       │   └── yarn.rs
│   │       ├── session.rs
│   │       ├── shim.rs
│   │       ├── signal.rs
│   │       ├── style.rs
│   │       ├── sync.rs
│   │       ├── tool/
│   │       │   ├── mod.rs
│   │       │   ├── node/
│   │       │   │   ├── fetch.rs
│   │       │   │   ├── metadata.rs
│   │       │   │   ├── mod.rs
│   │       │   │   └── resolve.rs
│   │       │   ├── npm/
│   │       │   │   ├── fetch.rs
│   │       │   │   ├── mod.rs
│   │       │   │   └── resolve.rs
│   │       │   ├── package/
│   │       │   │   ├── configure.rs
│   │       │   │   ├── install.rs
│   │       │   │   ├── manager.rs
│   │       │   │   ├── metadata.rs
│   │       │   │   ├── mod.rs
│   │       │   │   └── uninstall.rs
│   │       │   ├── pnpm/
│   │       │   │   ├── fetch.rs
│   │       │   │   ├── mod.rs
│   │       │   │   └── resolve.rs
│   │       │   ├── registry.rs
│   │       │   ├── serial.rs
│   │       │   └── yarn/
│   │       │       ├── fetch.rs
│   │       │       ├── metadata.rs
│   │       │       ├── mod.rs
│   │       │       └── resolve.rs
│   │       ├── toolchain/
│   │       │   ├── mod.rs
│   │       │   └── serial.rs
│   │       └── version/
│   │           ├── mod.rs
│   │           └── serial.rs
│   ├── volta-layout/
│   │   ├── Cargo.toml
│   │   └── src/
│   │       ├── lib.rs
│   │       ├── macros.rs
│   │       ├── v0.rs
│   │       ├── v1.rs
│   │       ├── v2.rs
│   │       ├── v3.rs
│   │       └── v4.rs
│   ├── volta-layout-macro/
│   │   ├── Cargo.toml
│   │   └── src/
│   │       ├── ast.rs
│   │       ├── ir.rs
│   │       └── lib.rs
│   └── volta-migrate/
│       ├── Cargo.toml
│       └── src/
│           ├── empty.rs
│           ├── lib.rs
│           ├── v0.rs
│           ├── v1.rs
│           ├── v2.rs
│           ├── v3/
│           │   └── config.rs
│           ├── v3.rs
│           └── v4.rs
├── dev/
│   ├── package.json
│   ├── rpm/
│   │   ├── build-rpm.sh
│   │   └── volta.spec
│   └── unix/
│       ├── SHASUMS256.txt
│       ├── boot-install.sh
│       ├── build.sh
│       ├── install.sh.in
│       ├── release.sh
│       ├── test-events
│       ├── tests/
│       │   └── install-script.bats
│       ├── volta-install-legacy.sh
│       └── volta-install.sh
├── rust-toolchain.toml
├── src/
│   ├── cli.rs
│   ├── command/
│   │   ├── completions.rs
│   │   ├── fetch.rs
│   │   ├── install.rs
│   │   ├── list/
│   │   │   ├── human.rs
│   │   │   ├── mod.rs
│   │   │   ├── plain.rs
│   │   │   └── toolchain.rs
│   │   ├── mod.rs
│   │   ├── pin.rs
│   │   ├── run.rs
│   │   ├── setup.rs
│   │   ├── uninstall.rs
│   │   ├── use.rs
│   │   └── which.rs
│   ├── common.rs
│   ├── main.rs
│   ├── volta-migrate.rs
│   └── volta-shim.rs
├── tests/
│   ├── acceptance/
│   │   ├── corrupted_download.rs
│   │   ├── direct_install.rs
│   │   ├── direct_uninstall.rs
│   │   ├── execute_binary.rs
│   │   ├── hooks.rs
│   │   ├── main.rs
│   │   ├── merged_platform.rs
│   │   ├── migrations.rs
│   │   ├── run_shim_directly.rs
│   │   ├── support/
│   │   │   ├── events_helpers.rs
│   │   │   ├── mod.rs
│   │   │   └── sandbox.rs
│   │   ├── verbose_errors.rs
│   │   ├── volta_bypass.rs
│   │   ├── volta_install.rs
│   │   ├── volta_pin.rs
│   │   ├── volta_run.rs
│   │   └── volta_uninstall.rs
│   ├── fixtures/
│   │   ├── cli-dist-2.4.159.tgz
│   │   ├── cli-dist-3.12.99.tgz
│   │   ├── cli-dist-3.2.42.tgz
│   │   ├── cli-dist-3.7.71.tgz
│   │   ├── npm-1.2.3.tgz
│   │   ├── npm-4.5.6.tgz
│   │   ├── npm-8.1.5.tgz
│   │   ├── pnpm-0.0.1.tgz
│   │   ├── pnpm-6.34.0.tgz
│   │   ├── pnpm-7.7.1.tgz
│   │   ├── volta-test-1.0.0.tgz
│   │   ├── yarn-0.0.1.tgz
│   │   ├── yarn-1.12.99.tgz
│   │   ├── yarn-1.2.42.tgz
│   │   ├── yarn-1.4.159.tgz
│   │   └── yarn-1.7.71.tgz
│   └── smoke/
│       ├── autodownload.rs
│       ├── direct_install.rs
│       ├── direct_upgrade.rs
│       ├── main.rs
│       ├── npm_link.rs
│       ├── package_migration.rs
│       ├── support/
│       │   ├── mod.rs
│       │   └── temp_project.rs
│       ├── volta_fetch.rs
│       ├── volta_install.rs
│       └── volta_run.rs
├── volta.iml
└── wix/
    ├── License.rtf
    ├── main.wxs
    └── shim.cmd

================================================
FILE CONTENTS
================================================

================================================
FILE: .cargo/config.toml
================================================
[target.x86_64-pc-windows-msvc]
rustflags = ["-C", "target-feature=+crt-static"]
[target.aarch64-pc-windows-msvc]
rustflags = ["-C", "target-feature=+crt-static"]


================================================
FILE: .github/dependabot.yml
================================================
version: 2
updates:
  - package-ecosystem: "cargo"
    open-pull-requests-limit: 5
    schedule:
      interval: "daily"
    directories:
      - "/"
      - "/crates/*"


================================================
FILE: .github/workflows/api-docs.yml
================================================
on:
  push:
    branches:
      - main

name: API Docs

jobs:
  publish:
    name: Build and publish
    runs-on: ubuntu-latest
    steps:
      - name: Check out code
        uses: actions/checkout@v4
        with:
          persist-credentials: false
      - name: Set up cargo
        uses: actions-rust-lang/setup-rust-toolchain@v1
      - name: Cargo Cache
        uses: Swatinem/rust-cache@v2
      - name: Build docs
        run: |
          cargo doc --all --features cross-platform-docs --no-deps --document-private-items
      - name: Prepare docs for publication
        run: |
          mkdir -p publish
          mv target/doc publish/main
          echo '<!doctype html><a href="volta">volta</a>' > publish/main/index.html
          echo '<!doctype html><a href="main">main</a>' > publish/index.html
      - name: Publish docs to GitHub pages
        uses: JamesIves/github-pages-deploy-action@releases/v3
        with:
          COMMIT_MESSAGE: Publishing GitHub Pages
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
          BRANCH: gh-pages
          FOLDER: publish
          SINGLE_COMMIT: true


================================================
FILE: .github/workflows/release.yml
================================================
on:
  push:
    tags:
      - v*
  pull_request:
    branches:
      - main

name: Production

jobs:
  linux:
    name: Build - Linux
    runs-on: ubuntu-latest
    steps:
      - name: Check out code
        uses: actions/checkout@v4
      - name: Set up docker buildx
        uses: docker/setup-buildx-action@v2
      - name: Build docker image
        uses: docker/build-push-action@v3
        with:
          cache-from: type=gha
          cache-to: type=gha,mode=max
          context: ./ci/docker
          push: false
          load: true
          tags: volta
      - name: Compile and package Volta
        run: docker run --volume ${PWD}:/root/workspace --workdir /root/workspace --rm --init --tty volta /root/workspace/ci/build-linux.sh volta-linux
      - name: Upload release artifact
        uses: actions/upload-artifact@v4
        with:
          name: linux
          path: target/release/volta-linux.tar.gz

  linux-arm:
    name: Build - Linux ARM
    runs-on: ubuntu-latest
    steps:
      - name: Check out code
        uses: actions/checkout@v4
      - name: Install cross-rs
        uses: taiki-e/install-action@v2
        with:
          tool: cross
      - name: Compile Volta
        run: cross build --release --target aarch64-unknown-linux-gnu
      - name: Package Volta
        run: |
          cd target/aarch64-unknown-linux-gnu/release && tar -zcvf "volta-linux-arm.tar.gz" volta volta-shim volta-migrate
      - name: Upload release artifact
        uses: actions/upload-artifact@v4
        with:
          name: linux-arm
          path: target/aarch64-unknown-linux-gnu/release/volta-linux-arm.tar.gz

  macos:
    name: Build - MacOS
    runs-on: macos-latest
    steps:
      - name: Check out code
        uses: actions/checkout@v4
      - name: Set up cargo
        uses: actions-rust-lang/setup-rust-toolchain@v1
        with:
          target: aarch64-apple-darwin,x86_64-apple-darwin
      - name: Compile and package Volta
        run: ./ci/build-macos.sh volta-macos
      - name: Upload release artifact
        uses: actions/upload-artifact@v4
        with:
          name: macos
          path: target/universal-apple-darwin/release/volta-macos.tar.gz

  windows:
    name: Build - Windows
    runs-on: windows-latest
    steps:
      - name: Check out code
        uses: actions/checkout@v4
      - name: Set up cargo
        uses: actions-rust-lang/setup-rust-toolchain@v1
        with:
          rustflags: ""
      - name: Add cargo-wix subcommand
        run: cargo install --locked cargo-wix
      - name: Compile and package installer
        run: |
          cargo wix --nocapture --package volta --output target\wix\volta-windows.msi
      - name: Create zip of binaries
        run: powershell Compress-Archive volta*.exe volta-windows.zip
        working-directory: ./target/release
      - name: Upload installer
        uses: actions/upload-artifact@v4
        with:
          name: windows-installer
          path: target/wix/volta-windows.msi
      - name: Upload zip
        uses: actions/upload-artifact@v4
        with:
          name: windows-zip
          path: target/release/volta-windows.zip

  windows-arm:
    name: Build - Windows ARM
    runs-on: windows-latest
    steps:
      - name: Check out code
        uses: actions/checkout@v4
      - name: Set up cargo
        uses: actions-rust-lang/setup-rust-toolchain@v1
        with:
          target: aarch64-pc-windows-msvc
          rustflags: ""
      - name: Add cargo-wix subcommand
        run: cargo install --locked cargo-wix
      - name: Compile and package installer
        run: |
          cargo wix --nocapture --package volta --target aarch64-pc-windows-msvc --output target\wix\volta-windows-arm.msi
      - name: Create zip of binaries
        run: powershell Compress-Archive volta*.exe volta-windows-arm.zip
        working-directory: ./target/aarch64-pc-windows-msvc/release
      - name: Upload installer
        uses: actions/upload-artifact@v4
        with:
          name: windows-installer-arm
          path: target/wix/volta-windows-arm.msi
      - name: Upload zip
        uses: actions/upload-artifact@v4
        with:
          name: windows-zip-arm
          path: target/aarch64-pc-windows-msvc/release/volta-windows-arm.zip

  release:
    name: Publish release
    runs-on: ubuntu-latest
    needs:
      - linux
      - linux-arm
      - macos
      - windows
      - windows-arm
    if: github.event_name == 'push'
    steps:
      - name: Check out code
        uses: actions/checkout@v4
      - name: Determine release version
        id: release_info
        env:
          TAG: ${{ github.ref }}
        run: echo "version=${TAG:11}" >> $GITHUB_OUTPUT
      - name: Fetch Linux artifact
        uses: actions/download-artifact@v4
        with:
          name: linux
          path: release
      - name: Fetch Linux ARM artifact
        uses: actions/download-artifact@v4
        with:
          name: linux-arm
          path: release
      - name: Fetch MacOS artifact
        uses: actions/download-artifact@v4
        with:
          name: macos
          path: release
      - name: Fetch Windows installer
        uses: actions/download-artifact@v4
        with:
          name: windows-installer
          path: release
      - name: Fetch Windows zip
        uses: actions/download-artifact@v4
        with:
          name: windows-zip
          path: release
      - name: Fetch Windows ARM installer
        uses: actions/download-artifact@v4
        with:
          name: windows-installer-arm
          path: release
      - name: Fetch Windows ARM zip
        uses: actions/download-artifact@v4
        with:
          name: windows-zip-arm
          path: release
      - name: Show release artifacts
        run: ls -la release
      - name: Create draft release
        id: create_release
        uses: actions/create-release@v1
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
        with:
          tag_name: ${{ github.ref }}
          release_name: ${{ github.ref }}
          draft: true
      - name: Upload Linux artifact
        uses: actions/upload-release-asset@v1
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
        with:
          upload_url: ${{ steps.create_release.outputs.upload_url }}
          asset_path: ./release/volta-linux.tar.gz
          asset_name: volta-${{ steps.release_info.outputs.version }}-linux.tar.gz
          asset_content_type: application/gzip
      - name: Upload Linux ARM artifact
        uses: actions/upload-release-asset@v1
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
        with:
          upload_url: ${{ steps.create_release.outputs.upload_url }}
          asset_path: ./release/volta-linux-arm.tar.gz
          asset_name: volta-${{ steps.release_info.outputs.version }}-linux-arm.tar.gz
          asset_content_type: application/gzip
      - name: Upload MacOS artifact
        uses: actions/upload-release-asset@v1
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
        with:
          upload_url: ${{ steps.create_release.outputs.upload_url }}
          asset_path: ./release/volta-macos.tar.gz
          asset_name: volta-${{ steps.release_info.outputs.version }}-macos.tar.gz
          asset_content_type: application/gzip
      - name: Upload Windows installer
        uses: actions/upload-release-asset@v1
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
        with:
          upload_url: ${{ steps.create_release.outputs.upload_url }}
          asset_path: ./release/volta-windows.msi
          asset_name: volta-${{ steps.release_info.outputs.version }}-windows-x86_64.msi
          asset_content_type: application/x-msi
      - name: Upload Windows zip
        uses: actions/upload-release-asset@v1
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
        with:
          upload_url: ${{ steps.create_release.outputs.upload_url }}
          asset_path: ./release/volta-windows.zip
          asset_name: volta-${{ steps.release_info.outputs.version }}-windows.zip
          asset_content_type: application/zip
      - name: Upload Windows ARM installer
        uses: actions/upload-release-asset@v1
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
        with:
          upload_url: ${{ steps.create_release.outputs.upload_url }}
          asset_path: ./release/volta-windows-arm.msi
          asset_name: volta-${{ steps.release_info.outputs.version }}-windows-arm64.msi
          asset_content_type: application/x-msi
      - name: Upload Windows ARM zip
        uses: actions/upload-release-asset@v1
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
        with:
          upload_url: ${{ steps.create_release.outputs.upload_url }}
          asset_path: ./release/volta-windows-arm.zip
          asset_name: volta-${{ steps.release_info.outputs.version }}-windows-arm64.zip
          asset_content_type: application/zip
      - name: Upload manifest file
        uses: actions/upload-release-asset@v1
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
        with:
          upload_url: ${{ steps.create_release.outputs.upload_url }}
          asset_path: ./ci/volta.manifest
          asset_name: volta.manifest
          asset_content_type: text/plain


================================================
FILE: .github/workflows/test.yml
================================================
on:
  push:
    branches:
      - main
  pull_request:
    branches:
      - main

name: Test

jobs:
  tests:
    strategy:
      matrix:
        os:
          - ubuntu
          - macos
          - windows
    name: Acceptance Tests (${{ matrix.os }})
    runs-on: ${{ matrix.os }}-latest
    env:
      RUST_BACKTRACE: full
    steps:
      - name: Check out code
        uses: actions/checkout@v4
      - name: Set up cargo
        uses: actions-rust-lang/setup-rust-toolchain@v1
      - name: Run tests
        run: |
          cargo test --all --features mock-network
      - name: Lint with clippy
        run: cargo clippy
      - name: Lint tests with clippy
        run: |
          cargo clippy --tests --features mock-network

  smoke-tests:
    name: Smoke Tests
    runs-on: macos-latest
    env:
      RUST_BACKTRACE: full
    steps:
      - name: Check out code
        uses: actions/checkout@v4
      - name: Set up cargo
        uses: actions-rust-lang/setup-rust-toolchain@v1
      - name: Run tests
        run: |
          cargo test --test smoke --features smoke-tests -- --test-threads 1

  shell-tests:
    name: Shell Script Tests
    runs-on: ubuntu-latest
    steps:
      - name: Setup BATS
        run: sudo npm install -g bats
      - name: Check out code
        uses: actions/checkout@v4
      - name: Run tests
        run: bats dev/unix/tests/

  check-formatting:
    name: Check code formatting
    runs-on: ubuntu-latest
    steps:
      - name: Check out code
        uses: actions/checkout@v4
      - name: Set up cargo
        uses: actions-rust-lang/setup-rust-toolchain@v1
      - name: Run check
        run: |
          cargo fmt --all --quiet -- --check

  validate-installer-checksum:
    name: Validate installer checksum
    runs-on: ubuntu-latest
    steps:
      - name: Check out code
        uses: actions/checkout@v4
      - name: Run check
        run: |
          cd dev/unix
          sha256sum --check SHASUMS256.txt


================================================
FILE: .gitignore
================================================
/target/
**/*.rs.bk
Notion.msi
Volta.msi
dev/windows/*.log
dev/windows/Notion.wixobj
dev/windows/Volta.wixobj
dev/windows/Notion.wixpdb
dev/windows/Volta.wixpdb
dev/unix/install.sh
/.idea/
/rls/
/rls*


# Created by https://www.gitignore.io/api/intellij (and then modified heavily)

### Intellij ###
# Ignore all IDEA files. This means you may have to rebuild the project on your
# new machines at times, but avoids checking in a bunch of files which are not
# generally relevant to other developers.
.idea

# CMake
cmake-build-*/

# File-based project format
*.iws

# IntelliJ
out/

# mpeltonen/sbt-idea plugin
.idea_modules/

# JIRA plugin
atlassian-ide-plugin.xml

# Crashlytics plugin (for Android Studio and IntelliJ)
com_crashlytics_export_strings.xml
crashlytics.properties
crashlytics-build.properties
fabric.properties

# End of https://www.gitignore.io/api/intellij


================================================
FILE: .vscode/launch.json
================================================
{
  "version": "0.2.0",
  "configurations": [
    {
      "type": "lldb",
      "request": "launch",
      "name": "Cargo run volta core",
      "cargo": {
        "args": ["run", "--bin", "volta"],
        "filter": {
          "kind": "bin",
          "name": "volta"
        }
      },
      "program": "${cargo:program}",
      "args": [],
      "sourceLanguages": ["rust"]
    },
    {
      "type": "lldb",
      "request": "launch",
      "name": "Cargo test volta core",
      "cargo": {
        "args": [
          "test",
          "--lib",
          "--no-run",
          "--package",
          "volta-core",
          "--",
          "--test-threads",
          "1"
        ],
        "filter": {
          "kind": "lib",
          "name": "volta-core"
        }
      },
      "program": "${cargo:program}",
      "args": [],
      "sourceLanguages": ["rust"]
    }
  ]
}


================================================
FILE: .vscode/settings.json
================================================
{
  "editor.formatOnSave": true
}


================================================
FILE: CODE_OF_CONDUCT.md
================================================
# Contributor Covenant Code of Conduct

## Our Pledge

In the interest of fostering an open and welcoming environment, we as
contributors and maintainers pledge to making participation in our project and
our community a harassment-free experience for everyone, regardless of age, body
size, disability, ethnicity, gender identity and expression, level of experience,
nationality, personal appearance, race, religion, or sexual identity and
orientation.

## Our Standards

Examples of behavior that contributes to creating a positive environment
include:

* Using welcoming and inclusive language
* Being respectful of differing viewpoints and experiences
* Gracefully accepting constructive criticism
* Focusing on what is best for the community
* Showing empathy towards other community members

Examples of unacceptable behavior by participants include:

* The use of sexualized language or imagery and unwelcome sexual attention or
  advances
* Trolling, insulting/derogatory comments, and personal or political attacks
* Public or private harassment
* Publishing others' private information, such as a physical or electronic
  address, without explicit permission
* Other conduct which could reasonably be considered inappropriate in a
  professional setting

## Our Responsibilities

Project maintainers are responsible for clarifying the standards of acceptable
behavior and are expected to take appropriate and fair corrective action in
response to any instances of unacceptable behavior.

Project maintainers have the right and responsibility to remove, edit, or
reject comments, commits, code, wiki edits, issues, and other contributions
that are not aligned to this Code of Conduct, or to ban temporarily or
permanently any contributor for other behaviors that they deem inappropriate,
threatening, offensive, or harmful.

## Scope

This Code of Conduct applies both within project spaces and in public spaces
when an individual is representing the project or its community. Examples of
representing a project or community include using an official project e-mail
address, posting via an official social media account, or acting as an appointed
representative at an online or offline event. Representation of a project may be
further defined and clarified by project maintainers.

## Enforcement

Instances of abusive, harassing, or otherwise unacceptable behavior may be
reported by contacting the project team at david.herman@gmail.com. All
complaints will be reviewed and investigated and will result in a response that
is deemed necessary and appropriate to the circumstances. The project team is
obligated to maintain confidentiality with regard to the reporter of an incident.
Further details of specific enforcement policies may be posted separately.

Project maintainers who do not follow or enforce the Code of Conduct in good
faith may face temporary or permanent repercussions as determined by other
members of the project's leadership.

## Attribution

This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4,
available at https://www.contributor-covenant.org/version/1/4/code-of-conduct.html

[homepage]: https://www.contributor-covenant.org


================================================
FILE: COMPATIBILITY.md
================================================
# Compatibility

Volta currently tests against the following platforms, and will treat it as a breaking change to drop support for them:

- macOS
    - x86-64
    - Apple Silicon
- Linux x86-64
- Windows x86-64

We compile release artifacts compatible with the following, and likewise will treat it as a breaking change to drop support for them:

- macOS v11
- RHEL and CentOS v7
- Windows 10

In general, Volta should build and run against any other modern hardware and operating system supported by stable Rust, and we will make a best effort not to break them. However, we do *not* include them in our SemVer guarantees or test against them.


================================================
FILE: CONTRIBUTING.md
================================================
Please see https://docs.volta.sh/contributing/


================================================
FILE: Cargo.toml
================================================
[package]
name = "volta"
version = "2.0.2"
authors = ["David Herman <david.herman@gmail.com>", "Charles Pierce <cpierce.grad@gmail.com>"]
license = "BSD-2-Clause"
repository = "https://github.com/volta-cli/volta"
edition = "2021"

[features]
cross-platform-docs = ["volta-core/cross-platform-docs"]
mock-network = ["mockito", "volta-core/mock-network"]
volta-dev = []
smoke-tests = []

[[bin]]
name = "volta-shim"
path = "src/volta-shim.rs"

[[bin]]
name = "volta-migrate"
path = "src/volta-migrate.rs"

[profile.release]
lto = "fat"
codegen-units = 1

[dependencies]
volta-core = { path = "crates/volta-core" }
serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0.135"
once_cell = "1.19.0"
log = { version = "0.4", features = ["std"] }
node-semver = "2"
clap = { version = "4.5.24", features = ["color", "derive", "wrap_help"] }
clap_complete = "4.5.46"
mockito = { version = "0.31.1", optional = true }
textwrap = "0.16.1"
which = "7.0.1"
dirs = "6.0.0"
volta-migrate = { path = "crates/volta-migrate" }

[target.'cfg(windows)'.dependencies]
winreg = "0.53.0"

[dev-dependencies]
hamcrest2 = "0.3.0"
envoy = "0.1.3"
ci_info = "0.14.14"
headers = "0.4"
cfg-if = "1.0"
test-support = { path = "crates/test-support" }

[workspace]


================================================
FILE: LICENSE
================================================
BSD 2-CLAUSE LICENSE

Copyright (c) 2017, The Volta Contributors.
All rights reserved.

This product includes:

Contributions from LinkedIn Corporation
Copyright (c) 2017, LinkedIn Corporation.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:

1. Redistributions of source code must retain the above copyright notice, this
   list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
   this list of conditions and the following disclaimer in the documentation
   and/or other materials provided with the distribution.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

The views and conclusions contained in the software and documentation are those
of the authors and should not be interpreted as representing official policies,
either expressed or implied, of the FreeBSD Project.


================================================
FILE: README.md
================================================
<p align="center">
  <a href="https://www.volta.sh/">
    <img alt="Volta" src="./volta.png?raw=true" width="360">
  </a>
</p>

<p align="center">
  The Hassle-Free JavaScript Tool Manager
</p>

<p align="center">
  <img alt="Production Build Status" src="https://github.com/volta-cli/volta/workflows/Production/badge.svg" />
  <a href="https://github.com/volta-cli/volta/actions?query=workflow%3ATest">
    <img alt="Test Status" src="https://github.com/volta-cli/volta/workflows/Test/badge.svg" />
  </a>
</p>

---

> [!IMPORTANT]
> **Volta is unmaintained.** Everything that works today should continue to do so for the foreseeable future, so if it is working for you, there is no particular *urgency* to migrate to another tool, but we will not be able to address breakages from new OS releases or other changes in the ecosystem, so you should put it on your maintenance roadmap at some point. We recommend migrating to [`mise`](https://mise.jdx.dev/). See [issue #2080](https://github.com/volta-cli/volta/issues/2080).

---


**Fast:** Install and run any JS tool quickly and seamlessly! Volta is built in Rust and ships as a snappy static binary.

**Reliable:** Ensure everyone in your project has the same tools—without interfering with their workflow.

**Universal:** No matter the package manager, Node runtime, or OS, one command is all you need: `volta install`.

## Features

- Speed 🚀
- Seamless, per-project version switching
- Cross-platform support, including Windows and all Unix shells
- Support for multiple package managers
- Stable tool installation—no reinstalling on every Node upgrade!
- Extensibility hooks for site-specific customization

## Installing Volta

Read the [Getting Started Guide](https://docs.volta.sh/guide/getting-started) on our website for detailed instructions on how to install Volta.

## Using Volta

Read the [Understanding Volta Guide](https://docs.volta.sh/guide/understanding) on our website for detailed instructions on how to use Volta.

## Contributing to Volta

Contributions are always welcome, no matter how large or small. Substantial feature ideas should be proposed as an [RFC](https://github.com/volta-cli/rfcs). Before contributing, please read the [code of conduct](CODE_OF_CONDUCT.md).

See the [Contributing Guide](https://docs.volta.sh/contributing/) on our website for detailed instructions on how to contribute to Volta.

## Who is using Volta?

<table>
  <tbody>
    <tr>
      <td align="center">
        <a href="https://github.com/microsoft/TypeScript" target="_blank">
          <img src="https://raw.githubusercontent.com/microsoft/TypeScript-Website/v2/packages/typescriptlang-org/static/branding/ts-logo-512.svg" alt="TypeScript" width="100" height="100">
        </a>
      </td>
      <td align="center">
        <a href="https://github.com/getsentry/sentry-javascript" target="_blank">
          <img src="https://avatars.githubusercontent.com/u/1396951?s=100" alt="Sentry" width="100" height="100">
        </a>
      </td>
    </tr>
  </tbody>
</table>

See [here](https://sourcegraph.com/search?q=context:global+%22volta%22+file:package.json&patternType=literal) for more Volta users.


================================================
FILE: RELEASES.md
================================================
# Version 2.0.2

- Dependency updates
- Improvements to header handling for HTTP requests (#1822, #1877)

# Version 2.0.1

- Improved accuracy of Node download progress bar on Windows (#1833)
- You should no longer run into errors about needing the VC++ Runtime on Windows (#1844)
- The data provided when installing a new Node version is now more relevant and accurate (#1846, #1848)
- Increased performance to make Volta even more responsive in typical use (#1849)
- `volta run` will now correctly handle flags in more situations (#1857)

# Version 2.0.0

- 🚨 (BREAKING) 🚨 We upgraded the version of Rust used to build Volta, which drops support for older versions of glibc & Linux kernel. See [the Rust announcement from August 2022](https://blog.rust-lang.org/2022/08/01/Increasing-glibc-kernel-requirements.html) for details about the supported versions. Notably, this means that we no longer support CentOS 6 (#1611)
- 🚨 (BREAKING) 🚨 Due to costs and changes in the code signing process, we have dropped the code signing for the Windows installer. We now recommend using `winget` to install Volta on Windows (#1650)
- 🎉 (NEW) 🎉 We now ship a pre-built binary for ARM Linux & ARM Windows (#1696, #1801)
- Volta no longer requires Developer Mode to be enabled on Windows (#1755)
- `volta uninstall` now provides better help & error messages to describe its use and limitations (#1628, #1786)
- Volta will now use a universal binary on Mac, rather than separate Intel- & ARM-specific builds (#1635)
- Switched to installing profile scripts into `.zshenv` by default, rather than `.zshrc` (#1657)
- Added a default shim for the `yarnpkg` command, which is an alias of `yarn` (#1670)
- Added a new `--very-verbose` flag to enable even more logging (note: we haven't yet implemented much additional logging) (#1815)
- Simplified the fetching process to remove an extra network request and resolve hangs (#1812)
- Several dependency upgrades and clean-up refactors from @tottoto

# Version 1.1.1

- Experimental support for pnpm (requires `VOLTA_FEATURE_PNPM` environment variable) (#1273)
- Fix to correctly import native root certificates (#1375)
- Better detection of executables provided by `yarn` (#1388, #1393)

# Version 1.1.0

- Added support for pinning / installing Yarn 3+ (#1305)
- Improved portability and installer effectiveness by removing dependency on OpenSSL (#1214)

# Version 1.0.8

- Fix for malformed `bin` entries when installing global packages (#997)
- Dependency updates

# Version 1.0.7

- Added build for Linux distros with OpenSSL 3.0 (#1211)

# Version 1.0.6

- Fixed panic when `stdout` is closed (#1058)
- Disabled global package interception when `--prefix` is provided (#1171)
- Numerous dependency updates

# Version 1.0.5

- Added error when attempting to install Node using `nvm` syntax (#1020)
- Avoid modifying shell config if the environment is already correct (#990)
- Prevent trying to read OS-generated files as package configs (#981)

# Version 1.0.4

- Fetch native Apple silicon versions of Node when available (#974)

# Version 1.0.3

- Fix pinning of `npm@bundled` when there is a custom default npm version (#957)
- Use correct binary name for scoped packages with a string `bin` entry in `package.json` (#969)

# Version 1.0.2

- Fix issues where `volta list` wasn't showing the correct information in all cases (#778, #926)
- Make detection of tool name case-insensitive on Windows (#941)
- Fix problem with `npm link` in a scoped package under npm 7 (#945)

# Version 1.0.1

- Create Native build for Apple Silicon machines (#915, #917)

# Version 1.0.0

- Support for `npm link` (#888, #889, #891)
- Support for `npm update -g` and `yarn global upgrade` (#895)
- Improvements in the handling of `npm` and `yarn` commands (#886, #887)

# Version 0.9.3

- Various fixes to event plugin logic (#892, #894, #897)

# Version 0.9.2

- Correctly detect Volta binary installation directory (#864)

# Version 0.9.1

- Fix an issue with installing globals using npm 7 (#858)

# Version 0.9.0

- Support Proxies through environment variables (#809, #851)
- Avoid unnecessary `exists` calls for files (#834)
- Rework package installs to allow for directly calling package manager (#848, #849)
- **Breaking Change**: Remove support for `packages` hooks (#817)

# Version 0.8.7

- Support fetching older versions of Yarn (#771)
- Correctly detect `zsh` environment with `ZDOTDIR` variable (#799)
- Prevent race conditions when installing tools (#684, #796)

# Version 0.8.6

- Improve parsing of `engines` when installing a package (#791, #792)

# Version 0.8.5

- Improve the stability of installing tools on systems with virus scanning software (#784)
- Make `volta uninstall` work correctly when the original install had an issue (#787)

# Version 0.8.4

- Add `{{filename}}` and `{{ext}}` (extension) replacements for `template` hooks (#774)
- Show better error when running `volta install yarn` without a Node version available (#763)

# Version 0.8.3

- Fix bug preventing custom `npm` versions from launching on Windows (#777)
- Fix for completions in `zsh` for `volta list` (#772)

# Version 0.8.2

- Add support for workspaces through the `extends` key in `package.json` (#755)
- Improve `volta setup` to make profile scripts more shareable across machines (#756)

# Version 0.8.1

- Fix panic when running `volta completions zsh` (#746)
- Improve startup latency by reducing binary size (#732, #733, #734, #735)

# Version 0.8.0

- Support for pinning / installing custom versions of `npm` (#691)
- New command: `volta run` which will let you run one-off commands using custom versions of Node / Yarn / npm (#713)
- Added default pretty formatter for `volta list` (#697)
- Improved setup of Volta environment to make it work in more scenarios (#666, #725)
- Bug fixes and performance improvements (#683, #701, #703, #704, #707, #717)

# Version 0.7.2

- Added `npm.cmd`, `npx.cmd`, and `yarn.cmd` on Windows to support tools that look for CMD files specifically (#663)
- Updated `volta setup` to also ensure that the shim symlinks are set up correctly (#662)

# Version 0.7.1

- Added warning when attempting to `volta uninstall` a package you don't have installed (#638)
- Added informational message about pinned project version when running `volta install` (#646)
- `volta completions` will attempt to create the output directory if it doesn't exist (#647)
- `volta install` will correctly handle script files that have CRLF as the line ending (#644)

# Version 0.7.0

- Removed deprecated commands `volta activate`, `volta deactivate`, and `volta current` (#620, #559)
- Simplified installer behavior and added data directory migration support (#619)
- Removed reliance on UNC paths when executing node scripts (#637)

# Version 0.6.8

- You can now use tagged versions when installing a tool with `volta install` (#604)
- `volta install <tool>` will now prefer LTS Node when pinning a version (#604)

# Version 0.6.7

- `volta pin` will no longer remove a closing newline from `package.json` (#603)
- New environment variable `VOLTA_BYPASS` will allow you to temporarily disable Volta shims (#603)

# Version 0.6.6

- Node and Yarn can now both be pinned in the same command `volta pin node yarn` (#593)
- Windows installer will now work on minimal Windows installs (e.g. Windows Sandbox) (#592)

# Version 0.6.5

- `volta list` Now always outputs to stdout, regardless of how it is called (#581)
- DEPRECATION: `volta activate` and `volta deactivate` are deprecated and will be removed in a future version (#571)

# Version 0.6.4

- `volta install` now works for installing packages from a private, authenticated registry (#554)
- `volta install` now has better diagnostic messages when things go wrong (#548)

# Version 0.6.3

- `volta install` will no longer error when installing a scoped binary package (#537)

# Version 0.6.2

- Added `volta list` command for inspecting the available tools and versions (#461)

# Version 0.6.1

- Windows users will see a spinner instead of a � when Volta is loading data (#511)
- Interrupting a tool with Ctrl+C will correctly wait for the tool to exit (#513)

# Version 0.6.0

- Allow installing 3rd-party binaries from private registries (#469)

# Version 0.5.7

- Prevent corrupting local cache by downloading tools to temp directory (#498)

# Version 0.5.6

- Improve expected behavior with Yarn in projects (#470)
- Suppress an erroneous "toolchain" key warning message (#486)

# Version 0.5.5

- Proper support for relative paths in Bin hooks (#468)
- Diagnostic messages for shims with `VOLTA_LOGLEVEL=debug` (#466)
- Preserve user order for multiple tool installs (#479)

# Version 0.5.4

- Show additional diagnostic messages when run with `--verbose` (#455)

# Version 0.5.3

- Prevent unnecessary warning output when not running interactively (#451)
- Fix a bug in load script for fish shell on Linux (#456)
- Improve wrapping behavior for warning messages (#453)

# Version 0.5.2

- Improve error messages when running a project-local binary fails (#426)
- Fix execution of user binaries on Windows (#445)

# Version 0.5.1

- Add per-project hooks configuration in `<PROJECT_ROOT>/.volta/hooks.json` (#411)
- Support backwards compatibility with `toolchain` key in `package.json` (#434)

# Version 0.5.0

- Rename to Volta: The JavaScript Launcher ⚡️
- Change `package.json` key to `volta` from `toolchain` (#413)
- Update `volta completions` behavior to be more usable (#416)
- Improve `volta which` to correctly find user tools (#419)
- Remove unneeded lookups of `package.json` files (#420)
- Cleanup of error messages and extraneous output (#421, #422)

# Version 0.4.1

- Allow tool executions to pass through to the system if no Notion platform exists (#372)
- Improve installer support for varied Linux distros

# Version 0.4.0

- Update `notion install` to use `tool@version` formatting for specifying a tool (#383, #403)
- Further error message improvements (#344, #395, #399, #400)
- Clean up bugs around installing and running packages (#368, #390, #394, #396)
- Include success messages when running `notion install` and `notion pin` (#397)

# Version 0.3.0

- Support `lts` pseudo-version for Node (#331)
- Error message improvements
- Add `notion install` and `notion uninstall` for package binaries
- Remove autoshimming

# Version 0.2.2

- Add `notion which` command (#293)
- Show progress when fetching Notion installer (#279)
- Improved styling for usage information (#283)
- Support for `fish` shell (#266, #290)
- Consolidate binaries, for a ~2/3 size reduction of Notion installer (#274)

# Version 0.2.1

- Move preventing globals behind a feature flag (#273)

# Version 0.2.0

- Add support for OpenSSL 1.1.1 (#267)
- Fix: ensure temp files are on the same volume (#257)
- Intercept global package installations (#248)
- Fix: make npx compatible with prelrease versions of npm (#239)
- Fix: make `notion deactivate` work infallibly, without loading any files (#237)
- Fix: make `"npm"` key optional in `package.json` (#233)
- Fix: publish latest Notion version via self-hosted endpoint (#230)
- Fix: eliminate excessive fetching and scanning for exact versions (#227)
- Rename `notion use` to `notion pin` (#226)
- Base filesystem isolation on `NOTION_HOME` env var (#224)
- Fix: robust progress bar logic (#221)
- Use JSON for internal state files (#220)
- Support for npm and npx (#205)
- Changes to directory layout (#181)

# Version 0.1.5

- Autoshimming! (#163)
- `notion deactivate` also unsets `NOTION_HOME` (#195)
- Implemented `notion activate` (#201)
- Fix for Yarn over-fetching bug (#203)

# Version 0.1.4

- Fix for `package.json` parsing bug (#156)

# Version 0.1.3

- Fix for Yarn path bug (#153)

# Version 0.1.2

- Correct logic for computing `latest` version of Node (#144)
- Don't crash if cache dir was deleted (#138)
- Improved tests (#135)

# Version 0.1.1

- Support for specifying `latest` as a version specifier (#133)
- Suppress scary-looking symlink warnings on reinstall (#132)
- Clearer error message for not-yet-implemented `notion install somebin` (#131)
- Support optional `v` prefix to version specifiers (#130)

# Version 0.1.0

First pre-release, supporting:

- macOS and Linux (bash-only)
- `notion install` (Node and Yarn only, no package binaries)
- `notion use`
- Proof-of-concept plugin API


================================================
FILE: ci/build-linux.sh
================================================
#!/bin/bash

set -e

# Activate the upgraded versions of GCC and binutils
# See https://linux.web.cern.ch/centos7/docs/softwarecollections/#inst
source /opt/rh/devtoolset-8/enable

echo "Building Volta"

cargo build --release

echo "Packaging Binaries"

cd target/release
tar -zcvf "$1.tar.gz" volta volta-shim volta-migrate


================================================
FILE: ci/build-macos.sh
================================================
#!/bin/bash

set -e

echo "Building Volta"

MACOSX_DEPLOYMENT_TARGET=11.0 cargo build --release --target=aarch64-apple-darwin
MACOSX_DEPLOYMENT_TARGET=11.0 cargo build --release --target=x86_64-apple-darwin

echo "Packaging Binaries"

mkdir -p target/universal-apple-darwin/release

for exe in volta volta-shim volta-migrate
do
    lipo -create -output target/universal-apple-darwin/release/$exe target/x86_64-apple-darwin/release/$exe target/aarch64-apple-darwin/release/$exe
done

cd target/universal-apple-darwin/release

tar -zcvf "$1.tar.gz" volta volta-shim volta-migrate


================================================
FILE: ci/docker/Dockerfile
================================================
FROM cern/cc7-base

# This repo file references a URL that is no longer valid. It also isn't used by the build
# toolchain, so we can safely remove it entirely
RUN rm /etc/yum.repos.d/epel.repo

# https://linux.web.cern.ch/centos7/docs/softwarecollections/#inst
# Tools needed for the build and setup process
RUN yum -y install wget tar
# Fetch the repo information for the devtoolset repo
RUN yum install -y centos-release-scl
# Install more recent GCC and binutils, to allow us to compile
RUN yum install -y devtoolset-8

RUN curl https://sh.rustup.rs -sSf | sh -s -- -y
ENV PATH="/root/.cargo/bin:${PATH}"


================================================
FILE: ci/volta.manifest
================================================
volta
volta-shim
volta-migrate


================================================
FILE: crates/archive/Cargo.toml
================================================
[package]
name = "archive"
version = "0.1.0"
authors = ["David Herman <david.herman@gmail.com>"]
edition = "2021"

[dependencies]
flate2 = "1.0"
tar = "0.4.13"
# Set features manually to drop usage of `time` crate: we do not rely on that
# set of capabilities, and it has a vulnerability. We also don't need to use
# every single compression algorithm feature since we are only downloading
# Node as a zip file
zip_rs = { version = "=2.1.6", package = "zip", default-features = false, features = ["deflate", "bzip2"] }
tee = "0.1.0"
fs-utils = { path = "../fs-utils" }
progress-read = { path = "../progress-read" }
verbatim = "0.1"
cfg-if = "1.0"
headers = "0.4"
thiserror = "2.0.0"
attohttpc = { version = "0.28", default-features = false, features = ["json", "compress", "tls-rustls-native-roots"] }
log = { version = "0.4", features = ["std"] }


================================================
FILE: crates/archive/src/lib.rs
================================================
//! This crate provides types for fetching and unpacking compressed
//! archives in tarball or zip format.
use std::fs::File;
use std::path::Path;

use attohttpc::header::HeaderMap;
use headers::{ContentLength, Header, HeaderMapExt};
use thiserror::Error;

mod tarball;
mod zip;

pub use crate::tarball::Tarball;
pub use crate::zip::Zip;

/// Error type for this crate
#[derive(Error, Debug)]
pub enum ArchiveError {
    #[error("HTTP failure ({0})")]
    HttpError(attohttpc::StatusCode),

    #[error("HTTP header '{0}' not found")]
    MissingHeaderError(&'static attohttpc::header::HeaderName),

    #[error("unexpected content length in HTTP response: {0}")]
    UnexpectedContentLengthError(u64),

    #[error("{0}")]
    IoError(#[from] std::io::Error),

    #[error("{0}")]
    AttohttpcError(#[from] attohttpc::Error),

    #[error("{0}")]
    ZipError(#[from] zip_rs::result::ZipError),
}

/// Metadata describing whether an archive comes from a local or remote origin.
#[derive(Copy, Clone)]
pub enum Origin {
    Local,
    Remote,
}

pub trait Archive {
    fn compressed_size(&self) -> u64;

    /// Unpacks the zip archive to the specified destination folder.
    fn unpack(
        self: Box<Self>,
        dest: &Path,
        progress: &mut dyn FnMut(&(), usize),
    ) -> Result<(), ArchiveError>;

    fn origin(&self) -> Origin;
}

cfg_if::cfg_if! {
    if #[cfg(unix)] {
        /// Load an archive in the native OS-preferred format from the specified file.
        ///
        /// On Windows, the preferred format is zip. On Unixes, the preferred format
        /// is tarball.
        pub fn load_native(source: File) -> Result<Box<dyn Archive>, ArchiveError> {
            Tarball::load(source)
        }

        /// Fetch a remote archive in the native OS-preferred format from the specified
        /// URL and store its results at the specified file path.
        ///
        /// On Windows, the preferred format is zip. On Unixes, the preferred format
        /// is tarball.
        pub fn fetch_native(url: &str, cache_file: &Path) -> Result<Box<dyn Archive>, ArchiveError> {
            Tarball::fetch(url, cache_file)
        }
    } else if #[cfg(windows)] {
        /// Load an archive in the native OS-preferred format from the specified file.
        ///
        /// On Windows, the preferred format is zip. On Unixes, the preferred format
        /// is tarball.
        pub fn load_native(source: File) -> Result<Box<dyn Archive>, ArchiveError> {
            Zip::load(source)
        }

        /// Fetch a remote archive in the native OS-preferred format from the specified
        /// URL and store its results at the specified file path.
        ///
        /// On Windows, the preferred format is zip. On Unixes, the preferred format
        /// is tarball.
        pub fn fetch_native(url: &str, cache_file: &Path) -> Result<Box<dyn Archive>, ArchiveError> {
            Zip::fetch(url, cache_file)
        }
    } else {
        compile_error!("Unsupported OS (expected 'unix' or 'windows').");
    }
}

/// Determines the length of an HTTP response's content in bytes, using
/// the HTTP `"Content-Length"` header.
fn content_length(headers: &HeaderMap) -> Result<u64, ArchiveError> {
    headers
        .typed_get()
        .map(|ContentLength(v)| v)
        .ok_or_else(|| ArchiveError::MissingHeaderError(ContentLength::name()))
}


================================================
FILE: crates/archive/src/tarball.rs
================================================
//! Provides types and functions for fetching and unpacking a Node installation
//! tarball in Unix operating systems.

use std::fs::File;
use std::io::Read;
use std::path::Path;

use super::{content_length, Archive, ArchiveError, Origin};
use flate2::read::GzDecoder;
use fs_utils::ensure_containing_dir_exists;
use progress_read::ProgressRead;
use tee::TeeReader;

/// A Node installation tarball.
pub struct Tarball {
    compressed_size: u64,
    data: Box<dyn Read>,
    origin: Origin,
}

impl Tarball {
    /// Loads a tarball from the specified file.
    pub fn load(source: File) -> Result<Box<dyn Archive>, ArchiveError> {
        let compressed_size = source.metadata()?.len();
        Ok(Box::new(Tarball {
            compressed_size,
            data: Box::new(source),
            origin: Origin::Local,
        }))
    }

    /// Initiate fetching of a tarball from the given URL, returning a
    /// tarball that can be streamed (and that tees its data to a local
    /// file as it streams).
    pub fn fetch(url: &str, cache_file: &Path) -> Result<Box<dyn Archive>, ArchiveError> {
        let (status, headers, response) = attohttpc::get(url).send()?.split();

        if !status.is_success() {
            return Err(ArchiveError::HttpError(status));
        }

        let compressed_size = content_length(&headers)?;

        ensure_containing_dir_exists(&cache_file)?;
        let file = File::create(cache_file)?;
        let data = Box::new(TeeReader::new(response, file));

        Ok(Box::new(Tarball {
            compressed_size,
            data,
            origin: Origin::Remote,
        }))
    }
}

impl Archive for Tarball {
    fn compressed_size(&self) -> u64 {
        self.compressed_size
    }
    fn unpack(
        self: Box<Self>,
        dest: &Path,
        progress: &mut dyn FnMut(&(), usize),
    ) -> Result<(), ArchiveError> {
        let decoded = GzDecoder::new(ProgressRead::new(self.data, (), progress));
        let mut tarball = tar::Archive::new(decoded);
        tarball.unpack(dest)?;
        Ok(())
    }
    fn origin(&self) -> Origin {
        self.origin
    }
}

#[cfg(test)]
pub mod tests {

    use crate::tarball::Tarball;
    use std::fs::File;
    use std::path::PathBuf;

    fn fixture_path(fixture_dir: &str) -> PathBuf {
        let mut cargo_manifest_dir = PathBuf::from(env!("CARGO_MANIFEST_DIR"));
        cargo_manifest_dir.push("fixtures");
        cargo_manifest_dir.push(fixture_dir);
        cargo_manifest_dir
    }

    #[test]
    fn test_load() {
        let mut test_file_path = fixture_path("tarballs");
        test_file_path.push("test-file.tar.gz");
        let test_file = File::open(test_file_path).expect("Couldn't open test file");
        let tarball = Tarball::load(test_file).expect("Failed to load tarball");

        assert_eq!(tarball.compressed_size(), 402);
    }
}


================================================
FILE: crates/archive/src/zip.rs
================================================
//! Provides types and functions for fetching and unpacking a Node installation
//! zip file in Windows operating systems.

use std::fs::File;
use std::io::Read;
use std::path::Path;

use super::{content_length, ArchiveError};
use fs_utils::ensure_containing_dir_exists;
use progress_read::ProgressRead;
use tee::TeeReader;
use verbatim::PathExt;
use zip_rs::unstable::stream::ZipStreamReader;

use super::Archive;
use super::Origin;

pub struct Zip {
    compressed_size: u64,
    data: Box<dyn Read>,
    origin: Origin,
}

impl Zip {
    /// Loads a cached Node zip archive from the specified file.
    pub fn load(source: File) -> Result<Box<dyn Archive>, ArchiveError> {
        let compressed_size = source.metadata()?.len();

        Ok(Box::new(Zip {
            compressed_size,
            data: Box::new(source),
            origin: Origin::Local,
        }))
    }

    /// Initiate fetching of a Node zip archive from the given URL, returning
    /// a `Remote` data source.
    pub fn fetch(url: &str, cache_file: &Path) -> Result<Box<dyn Archive>, ArchiveError> {
        let (status, headers, response) = attohttpc::get(url).send()?.split();

        if !status.is_success() {
            return Err(ArchiveError::HttpError(status));
        }

        let compressed_size = content_length(&headers)?;

        ensure_containing_dir_exists(&cache_file)?;
        let file = File::create(cache_file)?;
        let data = Box::new(TeeReader::new(response, file));

        Ok(Box::new(Zip {
            compressed_size,
            data,
            origin: Origin::Remote,
        }))
    }
}

impl Archive for Zip {
    fn compressed_size(&self) -> u64 {
        self.compressed_size
    }
    fn unpack(
        self: Box<Self>,
        dest: &Path,
        progress: &mut dyn FnMut(&(), usize),
    ) -> Result<(), ArchiveError> {
        // Use a verbatim path to avoid the legacy Windows 260 byte path limit.
        let dest: &Path = &dest.to_verbatim();
        let zip = ZipStreamReader::new(ProgressRead::new(self.data, (), progress));
        zip.extract(dest)?;
        Ok(())
    }
    fn origin(&self) -> Origin {
        self.origin
    }
}

#[cfg(test)]
pub mod tests {

    use crate::zip::Zip;
    use std::fs::File;
    use std::path::PathBuf;

    fn fixture_path(fixture_dir: &str) -> PathBuf {
        let mut cargo_manifest_dir = PathBuf::from(env!("CARGO_MANIFEST_DIR"));
        cargo_manifest_dir.push("fixtures");
        cargo_manifest_dir.push(fixture_dir);
        cargo_manifest_dir
    }

    #[test]
    fn test_load() {
        let mut test_file_path = fixture_path("zips");
        test_file_path.push("test-file.zip");
        let test_file = File::open(test_file_path).expect("Couldn't open test file");
        let zip = Zip::load(test_file).expect("Failed to load zip file");

        assert_eq!(zip.compressed_size(), 214);
    }
}


================================================
FILE: crates/fs-utils/Cargo.toml
================================================
[package]
name = "fs-utils"
version = "0.1.0"
authors = ["Michael Stewart <mikrostew@gmail.com>"]
edition = "2021"

[dependencies]


================================================
FILE: crates/fs-utils/src/lib.rs
================================================
//! This crate provides utilities for operating on the filesystem.

use std::fs;
use std::io;
use std::path::Path;

/// This creates the parent directory of the input path, assuming the input path is a file.
pub fn ensure_containing_dir_exists<P: AsRef<Path>>(path: &P) -> io::Result<()> {
    path.as_ref()
        .parent()
        .ok_or_else(|| {
            io::Error::new(
                io::ErrorKind::NotFound,
                format!(
                    "Could not determine directory information for {}",
                    path.as_ref().display()
                ),
            )
        })
        .and_then(fs::create_dir_all)
}


================================================
FILE: crates/progress-read/Cargo.toml
================================================
[package]
name = "progress-read"
version = "0.1.0"
authors = ["David Herman <david.herman@gmail.com>"]
edition = "2021"

[dependencies]


================================================
FILE: crates/progress-read/src/lib.rs
================================================
//! This crate provides an adapter for the `std::io::Read` trait to
//! allow reporting incremental progress to a callback function.

use std::io::{self, Read, Seek, SeekFrom};

/// A reader that reports incremental progress while reading.
pub struct ProgressRead<R: Read, T, F: FnMut(&T, usize) -> T> {
    source: R,
    accumulator: T,
    progress: F,
}

impl<R: Read, T, F: FnMut(&T, usize) -> T> Read for ProgressRead<R, T, F> {
    /// Read some bytes from the underlying reader into the specified buffer,
    /// and report progress to the progress callback. The progress callback is
    /// passed the current value of the accumulator as its first argument and
    /// the number of bytes read as its second argument. The result of the
    /// progress callback is stored as the updated value of the accumulator,
    /// to be passed to the next invocation of the callback.
    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
        let len = self.source.read(buf)?;
        let new_accumulator = {
            let progress = &mut self.progress;
            progress(&self.accumulator, len)
        };
        self.accumulator = new_accumulator;
        Ok(len)
    }
}

impl<R: Read, T, F: FnMut(&T, usize) -> T> ProgressRead<R, T, F> {
    /// Construct a new progress reader with the specified underlying reader,
    /// initial value for an accumulator, and progress callback.
    pub fn new(source: R, init: T, progress: F) -> ProgressRead<R, T, F> {
        ProgressRead {
            source,
            accumulator: init,
            progress,
        }
    }
}

impl<R: Read + Seek, T, F: FnMut(&T, usize) -> T> Seek for ProgressRead<R, T, F> {
    fn seek(&mut self, pos: SeekFrom) -> io::Result<u64> {
        self.source.seek(pos)
    }
}


================================================
FILE: crates/test-support/Cargo.toml
================================================
[package]
name = "test-support"
version = "0.1.0"
authors = ["David Herman <david.herman@gmail.com>"]
edition = "2021"

[dependencies]
hamcrest2 = "0.3.0"
serde_json = { version = "1.0.135" }
thiserror = "2.0.9"


================================================
FILE: crates/test-support/src/lib.rs
================================================
//! Utilities to use with acceptance tests in Volta.

#[macro_export]
macro_rules! ok_or_panic {
    { $e:expr } => {
        match $e {
            Ok(x) => x,
            Err(err) => panic!("{} failed with {}", stringify!($e), err),
        }
    };
}

pub mod matchers;
pub mod paths;
pub mod process;


================================================
FILE: crates/test-support/src/matchers.rs
================================================
use std::fmt;
use std::process::Output;
use std::str;

use crate::process::ProcessBuilder;

use hamcrest2::core::{MatchResult, Matcher};
use serde_json::{self, Value};

#[derive(Clone)]
pub struct Execs {
    expect_stdout: Option<String>,
    expect_stderr: Option<String>,
    expect_exit_code: Option<i32>,
    expect_stdout_contains: Vec<String>,
    expect_stderr_contains: Vec<String>,
    expect_either_contains: Vec<String>,
    expect_stdout_contains_n: Vec<(String, usize)>,
    expect_stdout_not_contains: Vec<String>,
    expect_stderr_not_contains: Vec<String>,
    expect_stderr_unordered: Vec<String>,
    expect_neither_contains: Vec<String>,
    expect_json: Option<Vec<Value>>,
}

impl Execs {
    /// Verify that stdout is equal to the given lines.
    /// See `lines_match` for supported patterns.
    pub fn with_stdout<S: ToString>(mut self, expected: S) -> Execs {
        self.expect_stdout = Some(expected.to_string());
        self
    }

    /// Verify that stderr is equal to the given lines.
    /// See `lines_match` for supported patterns.
    pub fn with_stderr<S: ToString>(mut self, expected: S) -> Execs {
        self._with_stderr(&expected);
        self
    }

    fn _with_stderr(&mut self, expected: &dyn ToString) {
        self.expect_stderr = Some(expected.to_string());
    }

    /// Verify the exit code from the process.
    pub fn with_status(mut self, expected: i32) -> Execs {
        self.expect_exit_code = Some(expected);
        self
    }

    /// Verify that stdout contains the given contiguous lines somewhere in
    /// its output.
    /// See `lines_match` for supported patterns.
    pub fn with_stdout_contains<S: ToString>(mut self, expected: S) -> Execs {
        self.expect_stdout_contains.push(expected.to_string());
        self
    }

    /// Verify that stderr contains the given contiguous lines somewhere in
    /// its output.
    /// See `lines_match` for supported patterns.
    pub fn with_stderr_contains<S: ToString>(mut self, expected: S) -> Execs {
        self.expect_stderr_contains.push(expected.to_string());
        self
    }

    /// Verify that either stdout or stderr contains the given contiguous
    /// lines somewhere in its output.
    /// See `lines_match` for supported patterns.
    pub fn with_either_contains<S: ToString>(mut self, expected: S) -> Execs {
        self.expect_either_contains.push(expected.to_string());
        self
    }

    /// Verify that stdout contains the given contiguous lines somewhere in
    /// its output, and should be repeated `number` times.
    /// See `lines_match` for supported patterns.
    pub fn with_stdout_contains_n<S: ToString>(mut self, expected: S, number: usize) -> Execs {
        self.expect_stdout_contains_n
            .push((expected.to_string(), number));
        self
    }

    /// Verify that stdout does not contain the given contiguous lines.
    /// See `lines_match` for supported patterns.
    /// See note on `with_stderr_does_not_contain`.
    pub fn with_stdout_does_not_contain<S: ToString>(mut self, expected: S) -> Execs {
        self.expect_stdout_not_contains.push(expected.to_string());
        self
    }

    /// Verify that stderr does not contain the given contiguous lines.
    /// See `lines_match` for supported patterns.
    ///
    /// Care should be taken when using this method because there is a
    /// limitless number of possible things that *won't* appear.  A typo means
    /// your test will pass without verifying the correct behavior. If
    /// possible, write the test first so that it fails, and then implement
    /// your fix/feature to make it pass.
    pub fn with_stderr_does_not_contain<S: ToString>(mut self, expected: S) -> Execs {
        self.expect_stderr_not_contains.push(expected.to_string());
        self
    }

    /// Verify that all of the stderr output is equal to the given lines,
    /// ignoring the order of the lines.
    /// See `lines_match` for supported patterns.
    /// This is useful when checking the output of `cargo build -v` since
    /// the order of the output is not always deterministic.
    /// Recommend use `with_stderr_contains` instead unless you really want to
    /// check *every* line of output.
    ///
    /// Be careful when using patterns such as `[..]`, because you may end up
    /// with multiple lines that might match, and this is not smart enough to
    /// do anything like longest-match.  For example, avoid something like:
    ///     [RUNNING] `rustc [..]
    ///     [RUNNING] `rustc --crate-name foo [..]
    /// This will randomly fail if the other crate name is `bar`, and the
    /// order changes.
    pub fn with_stderr_unordered<S: ToString>(mut self, expected: S) -> Execs {
        self.expect_stderr_unordered.push(expected.to_string());
        self
    }

    /// Verify the JSON output matches the given JSON.
    /// Typically used when testing cargo commands that emit JSON.
    /// Each separate JSON object should be separated by a blank line.
    /// Example:
    ///     assert_that(
    ///         p.cargo("metadata"),
    ///         execs().with_json(r#"
    ///             {"example": "abc"}
    ///             {"example": "def"}
    ///         "#)
    ///      );
    /// Objects should match in the order given.
    /// The order of arrays is ignored.
    /// Strings support patterns described in `lines_match`.
    /// Use `{...}` to match any object.
    pub fn with_json(mut self, expected: &str) -> Execs {
        self.expect_json = Some(
            expected
                .split("\n\n")
                .map(|obj| obj.parse().unwrap())
                .collect(),
        );
        self
    }

    fn match_output(&self, actual: &Output) -> MatchResult {
        self.match_status(actual)
            .and(self.match_stdout(actual))
            .and(self.match_stderr(actual))
    }

    fn match_status(&self, actual: &Output) -> MatchResult {
        match self.expect_exit_code {
            None => Ok(()),
            Some(code) if actual.status.code() == Some(code) => Ok(()),
            Some(_) => Err(format!(
                "exited with {}\n--- stdout\n{}\n--- stderr\n{}",
                actual.status,
                String::from_utf8_lossy(&actual.stdout),
                String::from_utf8_lossy(&actual.stderr)
            )),
        }
    }

    fn match_stdout(&self, actual: &Output) -> MatchResult {
        self.match_std(
            self.expect_stdout.as_ref(),
            &actual.stdout,
            "stdout",
            &actual.stderr,
            MatchKind::Exact,
        )?;
        for expect in self.expect_stdout_contains.iter() {
            self.match_std(
                Some(expect),
                &actual.stdout,
                "stdout",
                &actual.stderr,
                MatchKind::Partial,
            )?;
        }
        for expect in self.expect_stderr_contains.iter() {
            self.match_std(
                Some(expect),
                &actual.stderr,
                "stderr",
                &actual.stdout,
                MatchKind::Partial,
            )?;
        }
        for &(ref expect, number) in self.expect_stdout_contains_n.iter() {
            self.match_std(
                Some(expect),
                &actual.stdout,
                "stdout",
                &actual.stderr,
                MatchKind::PartialN(number),
            )?;
        }
        for expect in self.expect_stdout_not_contains.iter() {
            self.match_std(
                Some(expect),
                &actual.stdout,
                "stdout",
                &actual.stderr,
                MatchKind::NotPresent,
            )?;
        }
        for expect in self.expect_stderr_not_contains.iter() {
            self.match_std(
                Some(expect),
                &actual.stderr,
                "stderr",
                &actual.stdout,
                MatchKind::NotPresent,
            )?;
        }
        for expect in self.expect_stderr_unordered.iter() {
            self.match_std(
                Some(expect),
                &actual.stderr,
                "stderr",
                &actual.stdout,
                MatchKind::Unordered,
            )?;
        }
        for expect in self.expect_neither_contains.iter() {
            self.match_std(
                Some(expect),
                &actual.stdout,
                "stdout",
                &actual.stdout,
                MatchKind::NotPresent,
            )?;

            self.match_std(
                Some(expect),
                &actual.stderr,
                "stderr",
                &actual.stderr,
                MatchKind::NotPresent,
            )?;
        }

        for expect in self.expect_either_contains.iter() {
            let match_std = self.match_std(
                Some(expect),
                &actual.stdout,
                "stdout",
                &actual.stdout,
                MatchKind::Partial,
            );
            let match_err = self.match_std(
                Some(expect),
                &actual.stderr,
                "stderr",
                &actual.stderr,
                MatchKind::Partial,
            );

            if let (Err(_), Err(_)) = (match_std, match_err) {
                return Err(format!(
                    "expected to find:\n\
                     {}\n\n\
                     did not find in either output.",
                    expect
                ));
            }
        }

        if let Some(ref objects) = self.expect_json {
            let stdout = str::from_utf8(&actual.stdout)
                .map_err(|_| "stdout was not utf8 encoded".to_owned())?;
            let lines = stdout
                .lines()
                .filter(|line| line.starts_with('{'))
                .collect::<Vec<_>>();
            if lines.len() != objects.len() {
                return Err(format!(
                    "expected {} json lines, got {}, stdout:\n{}",
                    objects.len(),
                    lines.len(),
                    stdout
                ));
            }
            for (obj, line) in objects.iter().zip(lines) {
                self.match_json(obj, line)?;
            }
        }
        Ok(())
    }

    fn match_stderr(&self, actual: &Output) -> MatchResult {
        self.match_std(
            self.expect_stderr.as_ref(),
            &actual.stderr,
            "stderr",
            &actual.stdout,
            MatchKind::Exact,
        )
    }

    fn match_std(
        &self,
        expected: Option<&String>,
        actual: &[u8],
        description: &str,
        extra: &[u8],
        kind: MatchKind,
    ) -> MatchResult {
        let out = match expected {
            Some(out) => out,
            None => return Ok(()),
        };
        let actual = match str::from_utf8(actual) {
            Err(..) => return Err(format!("{} was not utf8 encoded", description)),
            Ok(actual) => actual,
        };
        // Let's not deal with \r\n vs \n on windows...
        let actual = actual.replace('\r', "");
        let actual = actual.replace('\t', "<tab>");

        match kind {
            MatchKind::Exact => {
                let a = actual.lines();
                let e = out.lines();

                let diffs = self.diff_lines(a, e, false);
                if diffs.is_empty() {
                    Ok(())
                } else {
                    Err(format!(
                        "differences:\n\
                         {}\n\n\
                         other output:\n\
                         `{}`",
                        diffs.join("\n"),
                        String::from_utf8_lossy(extra)
                    ))
                }
            }
            MatchKind::Partial => {
                let mut a = actual.lines();
                let e = out.lines();

                let mut diffs = self.diff_lines(a.clone(), e.clone(), true);
                #[allow(clippy::while_let_on_iterator)]
                while let Some(..) = a.next() {
                    let a = self.diff_lines(a.clone(), e.clone(), true);
                    if a.len() < diffs.len() {
                        diffs = a;
                    }
                }
                if diffs.is_empty() {
                    Ok(())
                } else {
                    Err(format!(
                        "expected to find:\n\
                         {}\n\n\
                         did not find in output:\n\
                         {}",
                        out, actual
                    ))
                }
            }
            MatchKind::PartialN(number) => {
                let mut a = actual.lines();
                let e = out.lines();

                let mut matches = 0;

                loop {
                    if self.diff_lines(a.clone(), e.clone(), true).is_empty() {
                        matches += 1;
                    }

                    if a.next().is_none() {
                        break;
                    }
                }

                if matches == number {
                    Ok(())
                } else {
                    Err(format!(
                        "expected to find {} occurrences:\n\
                         {}\n\n\
                         did not find in output:\n\
                         {}",
                        number, out, actual
                    ))
                }
            }
            MatchKind::NotPresent => {
                let mut a = actual.lines();
                let e = out.lines();

                let mut diffs = self.diff_lines(a.clone(), e.clone(), true);
                #[allow(clippy::while_let_on_iterator)]
                while let Some(..) = a.next() {
                    let a = self.diff_lines(a.clone(), e.clone(), true);
                    if a.len() < diffs.len() {
                        diffs = a;
                    }
                }
                if diffs.is_empty() {
                    Err(format!(
                        "expected not to find:\n\
                         {}\n\n\
                         but found in output:\n\
                         {}",
                        out, actual
                    ))
                } else {
                    Ok(())
                }
            }
            MatchKind::Unordered => {
                let mut a = actual.lines().collect::<Vec<_>>();
                let e = out.lines();

                for e_line in e {
                    match a.iter().position(|a_line| lines_match(e_line, a_line)) {
                        Some(index) => a.remove(index),
                        None => {
                            return Err(format!(
                                "Did not find expected line:\n\
                                 {}\n\
                                 Remaining available output:\n\
                                 {}\n",
                                e_line,
                                a.join("\n")
                            ));
                        }
                    };
                }
                if !a.is_empty() {
                    Err(format!(
                        "Output included extra lines:\n\
                         {}\n",
                        a.join("\n")
                    ))
                } else {
                    Ok(())
                }
            }
        }
    }

    fn match_json(&self, expected: &Value, line: &str) -> MatchResult {
        let actual = match line.parse() {
            Err(e) => return Err(format!("invalid json, {}:\n`{}`", e, line)),
            Ok(actual) => actual,
        };

        match find_mismatch(expected, &actual) {
            Some((expected_part, actual_part)) => Err(format!(
                "JSON mismatch\nExpected:\n{}\nWas:\n{}\nExpected part:\n{}\nActual part:\n{}\n",
                serde_json::to_string_pretty(expected).unwrap(),
                serde_json::to_string_pretty(&actual).unwrap(),
                serde_json::to_string_pretty(expected_part).unwrap(),
                serde_json::to_string_pretty(actual_part).unwrap(),
            )),
            None => Ok(()),
        }
    }

    fn diff_lines<'a>(
        &self,
        actual: str::Lines<'a>,
        expected: str::Lines<'a>,
        partial: bool,
    ) -> Vec<String> {
        let actual = actual.take(if partial {
            expected.clone().count()
        } else {
            usize::MAX
        });
        zip_all(actual, expected)
            .enumerate()
            .filter_map(|(i, (a, e))| match (a, e) {
                (Some(a), Some(e)) => {
                    if lines_match(e, a) {
                        None
                    } else {
                        Some(format!("{:3} - |{}|\n    + |{}|\n", i, e, a))
                    }
                }
                (Some(a), None) => Some(format!("{:3} -\n    + |{}|\n", i, a)),
                (None, Some(e)) => Some(format!("{:3} - |{}|\n    +\n", i, e)),
                (None, None) => panic!("Cannot get here"),
            })
            .collect()
    }
}

#[derive(Debug, PartialEq, Eq, Clone, Copy)]
enum MatchKind {
    Exact,
    Partial,
    PartialN(usize),
    NotPresent,
    Unordered,
}

/// Compare a line with an expected pattern.
/// - Use `[..]` as a wildcard to match 0 or more characters on the same line
///   (similar to `.*` in a regex).
/// - Use `[EXE]` to optionally add `.exe` on Windows (empty string on other
///   platforms).
/// - There is a wide range of macros (such as `[COMPILING]` or `[WARNING]`)
///   to match cargo's "status" output and allows you to ignore the alignment.
///   See `substitute_macros` for a complete list of macros.
pub fn lines_match(expected: &str, actual: &str) -> bool {
    // Let's not deal with / vs \ (windows...)
    let expected = expected.replace('\\', "/");
    let mut actual: &str = &actual.replace('\\', "/");
    let expected = substitute_macros(&expected);
    for (i, part) in expected.split("[..]").enumerate() {
        match actual.find(part) {
            Some(j) => {
                if i == 0 && j != 0 {
                    return false;
                }
                actual = &actual[j + part.len()..];
            }
            None => return false,
        }
    }
    actual.is_empty() || expected.ends_with("[..]")
}

#[test]
fn lines_match_works() {
    assert!(lines_match("a b", "a b"));
    assert!(lines_match("a[..]b", "a b"));
    assert!(lines_match("a[..]", "a b"));
    assert!(lines_match("[..]", "a b"));
    assert!(lines_match("[..]b", "a b"));

    assert!(!lines_match("[..]b", "c"));
    assert!(!lines_match("b", "c"));
    assert!(!lines_match("b", "cb"));
}

// Compares JSON object for approximate equality.
// You can use `[..]` wildcard in strings (useful for OS dependent things such
// as paths).  You can use a `"{...}"` string literal as a wildcard for
// arbitrary nested JSON (useful for parts of object emitted by other programs
// (e.g. rustc) rather than Cargo itself).  Arrays are sorted before comparison.
fn find_mismatch<'a>(expected: &'a Value, actual: &'a Value) -> Option<(&'a Value, &'a Value)> {
    use serde_json::Value::*;
    match (expected, actual) {
        (Number(l), Number(r)) if l == r => None,
        (Bool(l), Bool(r)) if l == r => None,
        (String(l), String(r)) if lines_match(l, r) => None,
        (Array(l), Array(r)) => {
            if l.len() != r.len() {
                return Some((expected, actual));
            }

            let mut l = l.iter().collect::<Vec<_>>();
            let mut r = r.iter().collect::<Vec<_>>();

            l.retain(
                |l| match r.iter().position(|r| find_mismatch(l, r).is_none()) {
                    Some(i) => {
                        r.remove(i);
                        false
                    }
                    None => true,
                },
            );

            if !l.is_empty() {
                assert!(!r.is_empty());
                Some((l[0], r[0]))
            } else {
                assert_eq!(r.len(), 0);
                None
            }
        }
        (Object(l), Object(r)) => {
            let same_keys = l.len() == r.len() && l.keys().all(|k| r.contains_key(k));
            if !same_keys {
                return Some((expected, actual));
            }

            l.values()
                .zip(r.values())
                .find_map(|(l, r)| find_mismatch(l, r))
        }
        (Null, Null) => None,
        // magic string literal "{...}" acts as wildcard for any sub-JSON
        (String(l), _) if l == "{...}" => None,
        _ => Some((expected, actual)),
    }
}

struct ZipAll<I1: Iterator, I2: Iterator> {
    first: I1,
    second: I2,
}

impl<T, I1: Iterator<Item = T>, I2: Iterator<Item = T>> Iterator for ZipAll<I1, I2> {
    type Item = (Option<T>, Option<T>);
    fn next(&mut self) -> Option<(Option<T>, Option<T>)> {
        let first = self.first.next();
        let second = self.second.next();

        match (first, second) {
            (None, None) => None,
            (a, b) => Some((a, b)),
        }
    }
}

fn zip_all<T, I1: Iterator<Item = T>, I2: Iterator<Item = T>>(a: I1, b: I2) -> ZipAll<I1, I2> {
    ZipAll {
        first: a,
        second: b,
    }
}

impl fmt::Display for Execs {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        write!(f, "execs")
    }
}

impl fmt::Debug for Execs {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        write!(f, "execs")
    }
}

impl Matcher<ProcessBuilder> for Execs {
    fn matches(&self, mut process: ProcessBuilder) -> MatchResult {
        self.matches(&mut process)
    }
}

impl<'a> Matcher<&'a mut ProcessBuilder> for Execs {
    fn matches(&self, process: &'a mut ProcessBuilder) -> MatchResult {
        println!("running {}", process);
        let res = process.exec_with_output();

        match res {
            Ok(out) => self.match_output(&out),
            Err(err) => {
                if let Some(out) = &err.output {
                    return self.match_output(out);
                }
                Err(format!("could not exec process {}: {}", process, err))
            }
        }
    }
}

impl Matcher<Output> for Execs {
    fn matches(&self, output: Output) -> MatchResult {
        self.match_output(&output)
    }
}

pub fn execs() -> Execs {
    Execs {
        expect_stdout: None,
        expect_stderr: None,
        expect_exit_code: Some(0),
        expect_stdout_contains: Vec::new(),
        expect_stderr_contains: Vec::new(),
        expect_either_contains: Vec::new(),
        expect_stdout_contains_n: Vec::new(),
        expect_stdout_not_contains: Vec::new(),
        expect_stderr_not_contains: Vec::new(),
        expect_stderr_unordered: Vec::new(),
        expect_neither_contains: Vec::new(),
        expect_json: None,
    }
}

fn substitute_macros(input: &str) -> String {
    let macros = [
        ("[RUNNING]", "     Running"),
        ("[COMPILING]", "   Compiling"),
        ("[CHECKING]", "    Checking"),
        ("[CREATED]", "     Created"),
        ("[FINISHED]", "    Finished"),
        ("[ERROR]", "error:"),
        ("[WARNING]", "warning:"),
        ("[DOCUMENTING]", " Documenting"),
        ("[FRESH]", "       Fresh"),
        ("[UPDATING]", "    Updating"),
        ("[ADDING]", "      Adding"),
        ("[REMOVING]", "    Removing"),
        ("[DOCTEST]", "   Doc-tests"),
        ("[PACKAGING]", "   Packaging"),
        ("[DOWNLOADING]", " Downloading"),
        ("[UPLOADING]", "   Uploading"),
        ("[VERIFYING]", "   Verifying"),
        ("[ARCHIVING]", "   Archiving"),
        ("[INSTALLING]", "  Installing"),
        ("[REPLACING]", "   Replacing"),
        ("[UNPACKING]", "   Unpacking"),
        ("[SUMMARY]", "     Summary"),
        ("[FIXING]", "      Fixing"),
        ("[EXE]", if cfg!(windows) { ".exe" } else { "" }),
    ];
    let mut result = input.to_owned();
    for &(pat, subst) in &macros {
        result = result.replace(pat, subst)
    }
    result
}


================================================
FILE: crates/test-support/src/paths.rs
================================================
use std::cell::Cell;
use std::env;
use std::fs;
use std::path::{Path, PathBuf};
use std::sync::atomic::{AtomicUsize, Ordering};
use std::sync::Once;

static SMOKE_TEST_DIR: &str = "smoke_test";
static NEXT_ID: AtomicUsize = AtomicUsize::new(0);

thread_local!(static TASK_ID: usize = NEXT_ID.fetch_add(1, Ordering::SeqCst));

// creates the root directory for the tests (once), and
// initializes the root and home directories for the current task
fn init() {
    static GLOBAL_INIT: Once = Once::new();
    thread_local!(static LOCAL_INIT: Cell<bool> = Cell::new(false));
    GLOBAL_INIT.call_once(|| {
        global_root().mkdir_p();
    });
    LOCAL_INIT.with(|i| {
        if i.get() {
            return;
        }
        i.set(true);
        root().rm_rf();
        home().mkdir_p();
    })
}

// the root directory for the smoke tests, in `target/smoke_test`
fn global_root() -> PathBuf {
    let mut path = ok_or_panic! { env::current_exe() };
    path.pop(); // chop off exe name
    path.pop(); // chop off 'debug'

    // If `cargo test` is run manually then our path looks like
    // `target/debug/foo`, in which case our `path` is already pointing at
    // `target`. If, however, `cargo test --target $target` is used then the
    // output is `target/$target/debug/foo`, so our path is pointing at
    // `target/$target`. Here we conditionally pop the `$target` name.
    if path.file_name().and_then(|s| s.to_str()) != Some("target") {
        path.pop();
    }

    path.join(SMOKE_TEST_DIR)
}

pub fn root() -> PathBuf {
    init();
    global_root().join(TASK_ID.with(|my_id| format!("t{}", my_id)))
}

pub fn home() -> PathBuf {
    root().join("home")
}

enum Remove {
    File,
    Dir,
}
impl Remove {
    fn to_str(&self) -> &'static str {
        match *self {
            Remove::File => "remove file",
            Remove::Dir => "remove dir",
        }
    }

    fn at(&self, path: &Path) {
        if cfg!(windows) {
            let mut p = ok_or_panic!(path.metadata()).permissions();
            // This lint rule is not applicable: this is in a `cfg!(windows)` block.
            #[allow(clippy::permissions_set_readonly_false)]
            p.set_readonly(false);
            ok_or_panic! { fs::set_permissions(path, p) };
        }
        match *self {
            Remove::File => fs::remove_file(path),
            Remove::Dir => fs::remove_dir_all(path), // ensure all dir contents are removed
        }
        .unwrap_or_else(|e| {
            panic!("failed to {} {}: {}", self.to_str(), path.display(), e);
        })
    }
}

pub trait PathExt {
    fn rm(&self);
    fn rm_rf(&self);
    fn rm_contents(&self);
    fn ensure_empty(&self);
    fn mkdir_p(&self);
}

impl PathExt for Path {
    // delete a file if it exists
    fn rm(&self) {
        if !self.exists() {
            return;
        }
        // On windows we can't remove a readonly file, and git will
        // often clone files as readonly. As a result, we have some
        // special logic to remove readonly files on windows.
        Remove::File.at(self);
    }

    /* Technically there is a potential race condition, but we don't
     * care all that much for our tests
     */
    fn rm_rf(&self) {
        if !self.exists() {
            return;
        }
        self.rm_contents();
        Remove::Dir.at(self);
    }

    // remove directory contents but not the directory itself
    fn rm_contents(&self) {
        for file in ok_or_panic! { fs::read_dir(self) } {
            let file = ok_or_panic! { file };
            if file.file_type().map(|m| m.is_dir()).unwrap_or(false) {
                file.path().rm_rf();
            } else {
                file.path().rm();
            }
        }
    }

    // ensure the directory is created and empty
    fn ensure_empty(&self) {
        self.mkdir_p();
        self.rm_contents();
    }

    // create all paths up to the input path
    fn mkdir_p(&self) {
        fs::create_dir_all(self)
            .unwrap_or_else(|e| panic!("failed to mkdir_p {}: {}", self.display(), e))
    }
}


================================================
FILE: crates/test-support/src/process.rs
================================================
use std::collections::HashMap;
use std::env;
use std::ffi::{OsStr, OsString};
use std::fmt;
use std::path::Path;
use std::process::{Command, ExitStatus, Output};
use std::str;

use thiserror::Error;

/// A builder object for an external process, similar to `std::process::Command`.
#[derive(Clone, Debug)]
pub struct ProcessBuilder {
    /// The program to execute.
    program: OsString,
    /// A list of arguments to pass to the program.
    args: Vec<OsString>,
    /// Any environment variables that should be set for the program.
    env: HashMap<String, Option<OsString>>,
    /// Which directory to run the program from.
    cwd: Option<OsString>,
}

impl fmt::Display for ProcessBuilder {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        write!(f, "`{}", self.program.to_string_lossy())?;

        for arg in &self.args {
            write!(f, " {}", arg.to_string_lossy())?;
        }

        write!(f, "`")
    }
}

impl ProcessBuilder {
    /// (chainable) Set the executable for the process.
    pub fn program<T: AsRef<OsStr>>(&mut self, program: T) -> &mut ProcessBuilder {
        self.program = program.as_ref().to_os_string();
        self
    }

    /// (chainable) Add an arg to the args list.
    pub fn arg<T: AsRef<OsStr>>(&mut self, arg: T) -> &mut ProcessBuilder {
        self.args.push(arg.as_ref().to_os_string());
        self
    }

    /// (chainable) Add many args to the args list.
    pub fn args<T: AsRef<OsStr>>(&mut self, arguments: &[T]) -> &mut ProcessBuilder {
        self.args
            .extend(arguments.iter().map(|t| t.as_ref().to_os_string()));
        self
    }

    /// (chainable) Replace args with new args list
    pub fn args_replace<T: AsRef<OsStr>>(&mut self, arguments: &[T]) -> &mut ProcessBuilder {
        self.args = arguments
            .iter()
            .map(|t| t.as_ref().to_os_string())
            .collect();
        self
    }

    /// (chainable) Set the current working directory of the process
    pub fn cwd<T: AsRef<OsStr>>(&mut self, path: T) -> &mut ProcessBuilder {
        self.cwd = Some(path.as_ref().to_os_string());
        self
    }

    /// (chainable) Set an environment variable for the process.
    pub fn env<T: AsRef<OsStr>>(&mut self, key: &str, val: T) -> &mut ProcessBuilder {
        self.env
            .insert(key.to_string(), Some(val.as_ref().to_os_string()));
        self
    }

    /// (chainable) Unset an environment variable for the process.
    pub fn env_remove(&mut self, key: &str) -> &mut ProcessBuilder {
        self.env.insert(key.to_string(), None);
        self
    }

    /// Get the executable name.
    pub fn get_program(&self) -> &OsString {
        &self.program
    }

    /// Get the program arguments
    pub fn get_args(&self) -> &[OsString] {
        &self.args
    }

    /// Get the current working directory for the process
    pub fn get_cwd(&self) -> Option<&Path> {
        self.cwd.as_ref().map(Path::new)
    }

    /// Get an environment variable as the process will see it (will inherit from environment
    /// unless explicitally unset).
    pub fn get_env(&self, var: &str) -> Option<OsString> {
        self.env
            .get(var)
            .cloned()
            .or_else(|| Some(env::var_os(var)))
            .and_then(|s| s)
    }

    /// Get all environment variables explicitly set or unset for the process (not inherited
    /// vars).
    pub fn get_envs(&self) -> &HashMap<String, Option<OsString>> {
        &self.env
    }

    /// Run the process, waiting for completion, and mapping non-success exit codes to an error.
    pub fn exec(&self) -> Result<(), ProcessError> {
        let mut command = self.build_command();

        let exit = match command.status() {
            Ok(e) => e,
            Err(_) => {
                return Err(process_error(
                    &format!("could not execute process {}", self),
                    None,
                    None,
                ));
            }
        };

        if exit.success() {
            Ok(())
        } else {
            Err(process_error(
                &format!("process didn't exit successfully: {}", self),
                Some(exit),
                None,
            ))
        }
    }

    /// Execute the process, returning the stdio output, or an error if non-zero exit status.
    pub fn exec_with_output(&self) -> Result<Output, ProcessError> {
        let mut command = self.build_command();

        let output = match command.output() {
            Ok(o) => o,
            Err(_) => {
                return Err(process_error(
                    &format!("could not execute process {}", self),
                    None,
                    None,
                ));
            }
        };

        if output.status.success() {
            Ok(output)
        } else {
            Err(process_error(
                &format!("process didn't exit successfully: {}", self),
                Some(output.status),
                Some(&output),
            ))
        }
    }

    /// Converts ProcessBuilder into a `std::process::Command`
    pub fn build_command(&self) -> Command {
        let mut command = Command::new(&self.program);
        if let Some(cwd) = self.get_cwd() {
            command.current_dir(cwd);
        }
        for arg in &self.args {
            command.arg(arg);
        }
        for (k, v) in &self.env {
            match *v {
                Some(ref v) => {
                    command.env(k, v);
                }
                None => {
                    command.env_remove(k);
                }
            }
        }
        command
    }
}

/// A helper function to create a `ProcessBuilder`.
pub fn process<T: AsRef<OsStr>>(cmd: T) -> ProcessBuilder {
    ProcessBuilder {
        program: cmd.as_ref().to_os_string(),
        args: Vec::new(),
        cwd: None,
        env: HashMap::new(),
    }
}

#[derive(Debug, Error)]
#[error("{desc}")]
pub struct ProcessError {
    pub desc: String,
    pub exit: Option<ExitStatus>,
    pub output: Option<Output>,
}

pub fn process_error(
    msg: &str,
    status: Option<ExitStatus>,
    output: Option<&Output>,
) -> ProcessError {
    let exit = match status {
        Some(s) => status_to_string(s),
        None => "never executed".to_string(),
    };
    let mut desc = format!("{} ({})", &msg, exit);

    if let Some(out) = output {
        match str::from_utf8(&out.stdout) {
            Ok(s) if !s.trim().is_empty() => {
                desc.push_str("\n--- stdout\n");
                desc.push_str(s);
            }
            Ok(..) | Err(..) => {}
        }
        match str::from_utf8(&out.stderr) {
            Ok(s) if !s.trim().is_empty() => {
                desc.push_str("\n--- stderr\n");
                desc.push_str(s);
            }
            Ok(..) | Err(..) => {}
        }
    }

    return ProcessError {
        desc,
        exit: status,
        output: output.cloned(),
    };

    fn status_to_string(status: ExitStatus) -> String {
        status.to_string()
    }
}


================================================
FILE: crates/validate-npm-package-name/Cargo.toml
================================================
[package]
name = "validate-npm-package-name"
version = "0.1.0"
authors = ["Chris Krycho <hello@chriskrycho.com>"]
edition = "2021"

[lib]

[dependencies]
once_cell = "1.19.0"
percent-encoding = "2.1.0"
regex = "1.1.6"


================================================
FILE: crates/validate-npm-package-name/src/lib.rs
================================================
//! A Rust implementation of the validation rules from the core JS package
//! [`validate-npm-package-name`](https://github.com/npm/validate-npm-package-name/).

use once_cell::sync::Lazy;
use percent_encoding::{utf8_percent_encode, AsciiSet, NON_ALPHANUMERIC};
use regex::Regex;

/// The set of characters to encode, matching the characters encoded by
/// [`encodeURIComponent`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/encodeURIComponent#description)
static ENCODE_URI_SET: &AsciiSet = &NON_ALPHANUMERIC
    .remove(b'-')
    .remove(b'_')
    .remove(b'.')
    .remove(b'!')
    .remove(b'~')
    .remove(b'*')
    .remove(b'\'')
    .remove(b'(')
    .remove(b')');

static SCOPED_PACKAGE: Lazy<Regex> =
    Lazy::new(|| Regex::new(r"^(?:@([^/]+?)[/])?([^/]+?)$").expect("regex is valid"));
static SPECIAL_CHARS: Lazy<Regex> = Lazy::new(|| Regex::new(r"[~'!()*]").expect("regex is valid"));
const BLACKLIST: [&str; 2] = ["node_modules", "favicon.ico"];

// Borrowed from https://github.com/juliangruber/builtins
const BUILTINS: [&str; 39] = [
    "assert",
    "buffer",
    "child_process",
    "cluster",
    "console",
    "constants",
    "crypto",
    "dgram",
    "dns",
    "domain",
    "events",
    "fs",
    "http",
    "https",
    "module",
    "net",
    "os",
    "path",
    "punycode",
    "querystring",
    "readline",
    "repl",
    "stream",
    "string_decoder",
    "sys",
    "timers",
    "tls",
    "tty",
    "url",
    "util",
    "vm",
    "zlib",
    "freelist",
    // excluded only in some versions
    "freelist",
    "v8",
    "process",
    "async_hooks",
    "http2",
    "perf_hooks",
];

#[derive(Debug, PartialEq, Eq)]
pub enum Validity {
    /// Valid for new and old packages
    Valid,

    /// Valid only for old packages
    ValidForOldPackages { warnings: Vec<String> },

    /// Not valid for new or old packages
    Invalid {
        warnings: Vec<String>,
        errors: Vec<String>,
    },
}

impl Validity {
    pub fn valid_for_old_packages(&self) -> bool {
        matches!(self, Validity::Valid | Validity::ValidForOldPackages { .. })
    }

    pub fn valid_for_new_packages(&self) -> bool {
        matches!(self, Validity::Valid)
    }
}

pub fn validate(name: &str) -> Validity {
    let mut warnings = Vec::new();
    let mut errors = Vec::new();

    if name.is_empty() {
        errors.push("name length must be greater than zero".into());
    }

    if name.starts_with('.') {
        errors.push("name cannot start with a period".into());
    }

    if name.starts_with('_') {
        errors.push("name cannot start with an underscore".into());
    }

    if name.trim() != name {
        errors.push("name cannot contain leading or trailing spaces".into());
    }

    // No funny business
    for blacklisted_name in BLACKLIST.iter() {
        if &name.to_lowercase() == blacklisted_name {
            errors.push(format!("{} is a blacklisted name", blacklisted_name));
        }
    }

    // Generate warnings for stuff that used to be allowed

    for builtin in BUILTINS.iter() {
        if name.to_lowercase() == *builtin {
            warnings.push(format!("{} is a core module name", builtin));
        }
    }

    // really-long-package-names-------------------------------such--length-----many---wow
    // the thisisareallyreallylongpackagenameitshouldpublishdowenowhavealimittothelengthofpackagenames-poch.
    if name.len() > 214 {
        warnings.push("name can no longer contain more than 214 characters".into());
    }

    // mIxeD CaSe nAMEs
    if name.to_lowercase() != name {
        warnings.push("name can no longer contain capital letters".into());
    }

    if name
        .split('/')
        .last()
        .map(|final_part| SPECIAL_CHARS.is_match(final_part))
        .unwrap_or(false)
    {
        warnings.push(r#"name can no longer contain special characters ("~\'!()*")"#.into());
    }

    if utf8_percent_encode(name, ENCODE_URI_SET).to_string() != name {
        // Maybe it's a scoped package name, like @user/package
        if let Some(captures) = SCOPED_PACKAGE.captures(name) {
            let valid_scope_name = captures
                .get(1)
                .map(|scope| scope.as_str())
                .map(|scope| utf8_percent_encode(scope, ENCODE_URI_SET).to_string() == scope)
                .unwrap_or(true);

            let valid_package_name = captures
                .get(2)
                .map(|package| package.as_str())
                .map(|package| utf8_percent_encode(package, ENCODE_URI_SET).to_string() == package)
                .unwrap_or(true);

            if valid_scope_name && valid_package_name {
                return done(warnings, errors);
            }
        }

        errors.push("name can only contain URL-friendly characters".into());
    }

    done(warnings, errors)
}

fn done(warnings: Vec<String>, errors: Vec<String>) -> Validity {
    match (warnings.len(), errors.len()) {
        (0, 0) => Validity::Valid,
        (_, 0) => Validity::ValidForOldPackages { warnings },
        (_, _) => Validity::Invalid { warnings, errors },
    }
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn traditional() {
        assert_eq!(validate("some-package"), Validity::Valid);
        assert_eq!(validate("example.com"), Validity::Valid);
        assert_eq!(validate("under_score"), Validity::Valid);
        assert_eq!(validate("period.js"), Validity::Valid);
        assert_eq!(validate("123numeric"), Validity::Valid);
        assert_eq!(
            validate("crazy!"),
            Validity::ValidForOldPackages {
                warnings: vec![
                    r#"name can no longer contain special characters ("~\'!()*")"#.into()
                ]
            }
        );
    }

    #[test]
    fn scoped() {
        assert_eq!(validate("@npm/thingy"), Validity::Valid);
        assert_eq!(
            validate("@npm-zors/money!time.js"),
            Validity::ValidForOldPackages {
                warnings: vec![
                    r#"name can no longer contain special characters ("~\'!()*")"#.into()
                ]
            }
        );
    }

    #[test]
    fn invalid() {
        assert_eq!(
            validate(""),
            Validity::Invalid {
                errors: vec!["name length must be greater than zero".into()],
                warnings: vec![]
            }
        );

        assert_eq!(
            validate(".start-with-period"),
            Validity::Invalid {
                errors: vec!["name cannot start with a period".into()],
                warnings: vec![]
            }
        );

        assert_eq!(
            validate("_start-with-underscore"),
            Validity::Invalid {
                errors: vec!["name cannot start with an underscore".into()],
                warnings: vec![]
            }
        );

        assert_eq!(
            validate("contain:colons"),
            Validity::Invalid {
                errors: vec!["name can only contain URL-friendly characters".into()],
                warnings: vec![]
            }
        );

        assert_eq!(
            validate(" leading-space"),
            Validity::Invalid {
                errors: vec![
                    "name cannot contain leading or trailing spaces".into(),
                    "name can only contain URL-friendly characters".into()
                ],
                warnings: vec![]
            }
        );

        assert_eq!(
            validate("trailing-space "),
            Validity::Invalid {
                errors: vec![
                    "name cannot contain leading or trailing spaces".into(),
                    "name can only contain URL-friendly characters".into()
                ],
                warnings: vec![]
            }
        );

        assert_eq!(
            validate("s/l/a/s/h/e/s"),
            Validity::Invalid {
                errors: vec!["name can only contain URL-friendly characters".into()],
                warnings: vec![]
            }
        );

        assert_eq!(
            validate("node_modules"),
            Validity::Invalid {
                errors: vec!["node_modules is a blacklisted name".into()],
                warnings: vec![]
            }
        );

        assert_eq!(
            validate("favicon.ico"),
            Validity::Invalid {
                errors: vec!["favicon.ico is a blacklisted name".into()],
                warnings: vec![]
            }
        );
    }

    #[test]
    fn node_io_core() {
        assert_eq!(
            validate("http"),
            Validity::ValidForOldPackages {
                warnings: vec!["http is a core module name".into()]
            }
        );
    }

    #[test]
    fn long_package_names() {
        let one_too_long = "ifyouwanttogetthesumoftwonumberswherethosetwonumbersarechosenbyfindingthelargestoftwooutofthreenumbersandsquaringthemwhichismultiplyingthembyitselfthenyoushouldinputthreenumbersintothisfunctionanditwilldothatforyou-";
        let short_enough = "ifyouwanttogetthesumoftwonumberswherethosetwonumbersarechosenbyfindingthelargestoftwooutofthreenumbersandsquaringthemwhichismultiplyingthembyitselfthenyoushouldinputthreenumbersintothisfunctionanditwilldothatforyou";

        assert_eq!(
            validate(one_too_long),
            Validity::ValidForOldPackages {
                warnings: vec!["name can no longer contain more than 214 characters".into()]
            }
        );

        assert_eq!(validate(short_enough), Validity::Valid);
    }

    #[test]
    fn legacy_mixed_case() {
        assert_eq!(
            validate("CAPITAL-LETTERS"),
            Validity::ValidForOldPackages {
                warnings: vec!["name can no longer contain capital letters".into()]
            }
        );
    }
}


================================================
FILE: crates/volta-core/Cargo.toml
================================================
[package]
name = "volta-core"
version = "0.1.0"
authors = ["David Herman <david.herman@gmail.com>"]
edition = "2021"

[features]
mock-network = ["mockito"]
# The `cross-platform-docs` feature flag is used for generating API docs for
# multiple platforms in one build.
# See ci/publish-docs.yml for an example of how it's enabled.
# See volta-core::path for an example of where it's used.
cross-platform-docs = []

[dependencies]
terminal_size = "0.4.1"
indicatif = "0.17.9"
console = ">=0.11.3, <1.0.0"
readext = "0.1.0"
serde_json = { version = "1.0.135", features = ["preserve_order"] }
serde = { version = "1.0.217", features = ["derive"] }
archive = { path = "../archive" }
node-semver = "2"
cmdline_words_parser = "0.2.1"
fs-utils = { path = "../fs-utils" }
cfg-if = "1.0"
tempfile = "3.14.0"
os_info = "3.9.2"
detect-indent = "0.1"
envoy = "0.1.3"
mockito = { version = "0.31.1", optional = true }
regex = "1.11.1"
dirs = "6.0.0"
# We manually configure the feature list here because 0.4.16 includes the
# `oldtime` feature by default to avoid a breaking change. Additionally, using
# the feature list explicitly lets us drop the `wasmbind` feature, which we do
# not need.
chrono = { version = "0.4.39", default-features = false, features = ["alloc", "std", "clock"] }
validate-npm-package-name = { path = "../validate-npm-package-name" }
textwrap = "0.16.1"
log = { version = "0.4", features = ["std"] }
ctrlc = "3.4.5"
walkdir = "2.5.0"
volta-layout = { path = "../volta-layout" }
once_cell = "1.19.0"
dunce = "1.0.5"
ci_info = "0.14.14"
httpdate = "1"
headers = "0.4"
attohttpc = { version = "0.28", default-features = false, features = ["json", "compress", "tls-rustls-native-roots"] }
chain-map = "0.1.0"
indexmap = "2.7.0"
retry = "2"
fs2 = "0.4.3"
which = "7.0.1"

[target.'cfg(windows)'.dependencies]
winreg = "0.55.0"
junction = "1.2.0"


================================================
FILE: crates/volta-core/fixtures/basic/package.json
================================================
{
  "name": "basic-project",
  "version": "0.0.7",
  "description": "Testing that manifest pulls things out of this correctly",
  "license": "To Kill",
  "dependencies": {
    "@namespace/some-dep": "0.2.4",
    "rsvp": "^3.5.0"
  },
  "devDependencies": {
    "@namespaced/something-else": "^6.3.7",
    "eslint": "~4.8.0"
  },
  "volta": {
    "node": "6.11.1",
    "npm": "3.10.10",
    "yarn": "1.2.0"
  }
}


================================================
FILE: crates/volta-core/fixtures/basic/subdir/.gitkeep
================================================


================================================
FILE: crates/volta-core/fixtures/cycle-1/package.json
================================================
{
  "name": "cycle-1-project",
  "version": "0.0.1",
  "description": "Testing that project correctly detects a cycle between this and volta.json",
  "license": "To Kill",
  "volta": {
    "extends": "./volta.json"
  }
}


================================================
FILE: crates/volta-core/fixtures/cycle-1/volta.json
================================================
{
  "volta": {
    "extends": "./package.json"
  }
}


================================================
FILE: crates/volta-core/fixtures/cycle-2/package.json
================================================
{
  "name": "cycle-2-project",
  "version": "0.0.1",
  "description": "Testing that project correctly detects a cycle between workspace-1.json and workspace-2.json",
  "license": "To Kill",
  "volta": {
    "extends": "./workspace-1.json"
  }
}


================================================
FILE: crates/volta-core/fixtures/cycle-2/workspace-1.json
================================================
{
  "volta": {
    "extends": "./workspace-2.json"
  }
}


================================================
FILE: crates/volta-core/fixtures/cycle-2/workspace-2.json
================================================
{
  "volta": {
    "extends": "./workspace-1.json"
  }
}


================================================
FILE: crates/volta-core/fixtures/hooks/bins.json
================================================
{
  "node": {
    "distro": {
      "bin": "/some/bin/for/node/distro"
    },
    "latest": {
      "bin": "/some/bin/for/node/latest"
    },
    "index": {
      "bin": "/some/bin/for/node/index"
    }
  },
  "pnpm": {
    "distro": {
      "bin": "/bin/to/pnpm/distro"
    },
    "latest": {
      "bin": "/bin/to/pnpm/latest"
    },
    "index": {
      "bin": "/bin/to/pnpm/index"
    }
  },
  "yarn": {
    "distro": {
      "bin": "/bin/to/yarn/distro"
    },
    "latest": {
      "bin": "/bin/to/yarn/latest"
    },
    "index": {
      "bin": "/bin/to/yarn/index"
    }
  },
  "events": {
    "publish": {
      "bin": "/events/bin"
    }
  }
}


================================================
FILE: crates/volta-core/fixtures/hooks/event_url.json
================================================
{
  "events": {
    "publish": {
      "url": "https://google.com"
    }
  }
}


================================================
FILE: crates/volta-core/fixtures/hooks/format_github.json
================================================
{
  "node": {
    "index": {
      "prefix": "http://localhost/node/index/",
      "format": "github"
    }
  },
  "npm": {
    "index": {
      "prefix": "http://localhost/npm/index/",
      "format": "github"
    }
  },
  "pnpm": {
    "index": {
      "prefix": "http://localhost/pnpm/index/",
      "format": "github"
    }
  },
  "yarn": {
    "index": {
      "prefix": "http://localhost/yarn/index/",
      "format": "github"
    }
  }
}


================================================
FILE: crates/volta-core/fixtures/hooks/format_npm.json
================================================
{
  "node": {
    "index": {
      "prefix": "http://localhost/node/index/",
      "format": "npm"
    }
  },
  "npm": {
    "index": {
      "prefix": "http://localhost/npm/index/",
      "format": "npm"
    }
  },
  "pnpm": {
    "index": {
      "prefix": "http://localhost/pnpm/index/",
      "format": "npm"
    }
  },
  "yarn": {
    "index": {
      "prefix": "http://localhost/yarn/index/",
      "format": "npm"
    }
  }
}


================================================
FILE: crates/volta-core/fixtures/hooks/prefixes.json
================================================
{
  "node": {
    "distro": {
      "prefix": "http://localhost/node/distro/"
    },
    "latest": {
      "prefix": "http://localhost/node/latest/"
    },
    "index": {
      "prefix": "http://localhost/node/index/"
    }
  },
  "pnpm": {
    "distro": {
      "prefix": "http://localhost/pnpm/distro/"
    },
    "latest": {
      "prefix": "http://localhost/pnpm/latest/"
    },
    "index": {
      "prefix": "http://localhost/pnpm/index/"
    }
  },
  "yarn": {
    "distro": {
      "prefix": "http://localhost/yarn/distro/"
    },
    "latest": {
      "prefix": "http://localhost/yarn/latest/"
    },
    "index": {
      "prefix": "http://localhost/yarn/index/"
    }
  }
}


================================================
FILE: crates/volta-core/fixtures/hooks/project/.volta/hooks.json
================================================
{
  "node": {
    "distro": {
      "bin": "/some/bin/for/node/distro"
    },
    "latest": {
      "bin": "/some/bin/for/node/latest"
    },
    "index": {
      "bin": "/some/bin/for/node/index"
    }
  },
  "events": {
    "publish": {
      "bin": "/events/bin"
    }
  }
}


================================================
FILE: crates/volta-core/fixtures/hooks/project/package.json
================================================
{
  "this file": "causes this directory to be recognized as a project"
}


================================================
FILE: crates/volta-core/fixtures/hooks/templates.json
================================================
{
  "node": {
    "distro": {
      "template": "http://localhost/node/distro/{{version}}/"
    },
    "latest": {
      "template": "http://localhost/node/latest/{{version}}/"
    },
    "index": {
      "template": "http://localhost/node/index/{{version}}/"
    }
  },
  "pnpm": {
    "distro": {
      "template": "http://localhost/pnpm/distro/{{version}}/"
    },
    "latest": {
      "template": "http://localhost/pnpm/latest/{{version}}/"
    },
    "index": {
      "template": "http://localhost/pnpm/index/{{version}}/"
    }
  },
  "yarn": {
    "distro": {
      "template": "http://localhost/yarn/distro/{{version}}/"
    },
    "latest": {
      "template": "http://localhost/yarn/latest/{{version}}/"
    },
    "index": {
      "template": "http://localhost/yarn/index/{{version}}/"
    }
  }
}


================================================
FILE: crates/volta-core/fixtures/nested/package.json
================================================
{
  "name": "nested-project",
  "version": "0.0.1",
  "description": "Testing that project correctly detects a nested workspace",
  "license": "To Kill",
  "dependencies": {
    "lodash": "*"
  },
  "devDependencies": {
    "eslint": "*"
  },
  "volta": {
    "yarn": "1.11.0",
    "npm": "6.12.1",
    "node": "12.14.0"
  }
}


================================================
FILE: crates/volta-core/fixtures/nested/subproject/inner_project/package.json
================================================
{
  "name": "inner-project",
  "version": "0.0.1",
  "description": "Testing that project correctly detects a nested workspace",
  "license": "To Kill",
  "dependencies": {
    "express": "*"
  },
  "devDependencies": {
    "typescript": "*"
  },
  "volta": {
    "yarn": "1.22.4",
    "extends": "../package.json"
  }
}


================================================
FILE: crates/volta-core/fixtures/nested/subproject/package.json
================================================
{
  "name": "subproject",
  "version": "0.0.1",
  "description": "Testing that project correctly detects a nested workspace",
  "license": "To Kill",
  "dependencies": {
    "rsvp": "*"
  },
  "devDependencies": {
    "glob": "*"
  },
  "volta": {
    "yarn": "1.17.0",
    "npm": "6.9.0",
    "extends": "../package.json"
  }
}


================================================
FILE: crates/volta-core/fixtures/no_toolchain/package.json
================================================
{
  "name": "basic-project",
  "version": "0.0.7",
  "description": "Testing that manifest pulls things out of this correctly",
  "license": "To Kill",
  "dependencies": {
    "@namespace/some-dep": "0.2.4",
    "rsvp": "^3.5.0"
  },
  "devDependencies": {
    "@namespaced/something-else": "^6.3.7",
    "eslint": "~4.8.0"
  }
}


================================================
FILE: crates/volta-core/fixtures/yarn/pnp-cjs/.pnp.cjs
================================================
// plug and play


================================================
FILE: crates/volta-core/fixtures/yarn/pnp-cjs/package.json
================================================
{
  "name": "plug-n-play-cjs",
  "version": "2.0.0",
  "description": "Testing that Plug-n-Play things work",
  "license": "To Ill",
  "volta": {
    "node": "6.11.1",
    "npm": "3.10.10",
    "yarn": "3.2.0"
  }
}


================================================
FILE: crates/volta-core/fixtures/yarn/pnp-js/.pnp.js
================================================
// plug and play


================================================
FILE: crates/volta-core/fixtures/yarn/pnp-js/package.json
================================================
{
  "name": "plug-n-play-js",
  "version": "2.0.0",
  "description": "Testing that Plug-n-Play things work",
  "license": "To Ill",
  "volta": {
    "node": "6.11.1",
    "npm": "3.10.10",
    "yarn": "2.4.0"
  }
}


================================================
FILE: crates/volta-core/fixtures/yarn/yarnrc-yml/.yarnrc.yml
================================================
yarnPath: .yarn/releases/yarn-3.3.0.cjs

================================================
FILE: crates/volta-core/fixtures/yarn/yarnrc-yml/package.json
================================================
{
  "name": "yarnrc-yml",
  "version": "2.0.0",
  "description": "Testing that Yarn berry things work",
  "license": "To Ill",
  "volta": {
    "node": "6.11.1",
    "npm": "3.10.10",
    "yarn": "3.3.0"
  }
}


================================================
FILE: crates/volta-core/src/command.rs
================================================
use std::ffi::OsStr;
use std::process::Command;

use cfg_if::cfg_if;

cfg_if! {
    if #[cfg(windows)] {
        pub fn create_command<E>(exe: E) -> Command
        where
            E: AsRef<OsStr>
        {
            // Several of the node utilities are implemented as `.bat` or `.cmd` files
            // When executing those files with `Command`, we need to call them with:
            //    cmd.exe /C <COMMAND> <ARGUMENTS>
            // Instead of: <COMMAND> <ARGUMENTS>
            // See: https://github.com/rust-lang/rust/issues/42791 For a longer discussion
            let mut command = Command::new("cmd.exe");
            command.arg("/C");
            command.arg(exe);
            command
        }
    } else {
        pub fn create_command<E>(exe: E) -> Command
        where
            E: AsRef<OsStr>
        {
            Command::new(exe)
        }
    }
}


================================================
FILE: crates/volta-core/src/error/kind.rs
================================================
use std::fmt;
use std::path::PathBuf;

use super::ExitCode;
use crate::style::{text_width, tool_version};
use crate::tool;
use crate::tool::package::PackageManager;
use textwrap::{fill, indent};

const REPORT_BUG_CTA: &str =
    "Please rerun the command that triggered this error with the environment
variable `VOLTA_LOGLEVEL` set to `debug` and open an issue at
https://github.com/volta-cli/volta/issues with the details!";

const PERMISSIONS_CTA: &str = "Please ensure you have correct permissions to the Volta directory.";

#[derive(Debug)]
#[cfg_attr(test, derive(PartialEq, Eq))]
pub enum ErrorKind {
    /// Thrown when package tries to install a binary that is already installed.
    BinaryAlreadyInstalled {
        bin_name: String,
        existing_package: String,
        new_package: String,
    },

    /// Thrown when executing an external binary fails
    BinaryExecError,

    /// Thrown when a binary could not be found in the local inventory
    BinaryNotFound {
        name: String,
    },

    /// Thrown when building the virtual environment path fails
    BuildPathError,

    /// Thrown when unable to launch a command with VOLTA_BYPASS set
    BypassError {
        command: String,
    },

    /// Thrown when a user tries to `volta fetch` something other than node/yarn/npm.
    CannotFetchPackage {
        package: String,
    },

    /// Thrown when a user tries to `volta pin` something other than node/yarn/npm.
    CannotPinPackage {
        package: String,
    },

    /// Thrown when the Completions out-dir is not a directory
    CompletionsOutFileError {
        path: PathBuf,
    },

    /// Thrown when the containing directory could not be determined
    ContainingDirError {
        path: PathBuf,
    },

    CouldNotDetermineTool,

    /// Thrown when unable to start the migration executable
    CouldNotStartMigration,

    CreateDirError {
        dir: PathBuf,
    },

    /// Thrown when unable to create the layout file
    CreateLayoutFileError {
        file: PathBuf,
    },

    /// Thrown when unable to create a link to the shared global library directory
    CreateSharedLinkError {
        name: String,
    },

    /// Thrown when creating a temporary directory fails
    CreateTempDirError {
        in_dir: PathBuf,
    },

    /// Thrown when creating a temporary file fails
    CreateTempFileError {
        in_dir: PathBuf,
    },

    CurrentDirError,

    /// Thrown when deleting a directory fails
    DeleteDirectoryError {
        directory: PathBuf,
    },

    /// Thrown when deleting a file fails
    DeleteFileError {
        file: PathBuf,
    },

    DeprecatedCommandError {
        command: String,
        advice: String,
    },

    DownloadToolNetworkError {
        tool: tool::Spec,
        from_url: String,
    },

    /// Thrown when unable to execute a hook command
    ExecuteHookError {
        command: String,
    },

    /// Thrown when `volta.extends` keys result in an infinite cycle
    ExtensionCycleError {
        paths: Vec<PathBuf>,
        duplicate: PathBuf,
    },

    /// Thrown when determining the path to an extension manifest fails
    ExtensionPathError {
        path: PathBuf,
    },

    /// Thrown when a hook command returns a non-zero exit code
    HookCommandFailed {
        command: String,
    },

    /// Thrown when a hook contains multiple fields (prefix, template, or bin)
    HookMultipleFieldsSpecified,

    /// Thrown when a hook doesn't contain any of the known fields (prefix, template, or bin)
    HookNoFieldsSpecified,

    /// Thrown when determining the path to a hook fails
    HookPathError {
        command: String,
    },

    /// Thrown when determining the name of a newly-installed package fails
    InstalledPackageNameError,

    InvalidHookCommand {
        command: String,
    },

    /// Thrown when output from a hook command could not be read
    InvalidHookOutput {
        command: String,
    },

    /// Thrown when a user does e.g. `volta install node 12` instead of
    /// `volta install node@12`.
    InvalidInvocation {
        action: String,
        name: String,
        version: String,
    },

    /// Thrown when a user does e.g. `volta install 12` instead of
    /// `volta install node@12`.
    InvalidInvocationOfBareVersion {
        action: String,
        version: String,
    },

    /// Thrown when a format other than "npm" or "github" is given for yarn.index in the hooks
    InvalidRegistryFormat {
        format: String,
    },

    /// Thrown when a tool name is invalid per npm's rules.
    InvalidToolName {
        name: String,
        errors: Vec<String>,
    },

    /// Thrown when unable to acquire a lock on the Volta directory
    LockAcquireError,

    /// Thrown when pinning or installing npm@bundled and couldn't detect the bundled version
    NoBundledNpm {
        command: String,
    },

    /// Thrown when pnpm is not set at the command-line
    NoCommandLinePnpm,

    /// Thrown when Yarn is not set at the command-line
    NoCommandLineYarn,

    /// Thrown when a user tries to install a Yarn or npm version before installing a Node version.
    NoDefaultNodeVersion {
        tool: String,
    },

    /// Thrown when there is no Node version matching a requested semver specifier.
    NodeVersionNotFound {
        matching: String,
    },

    NoHomeEnvironmentVar,

    /// Thrown when the install dir could not be determined
    NoInstallDir,

    NoLocalDataDir,

    /// Thrown when a user tries to pin a npm, pnpm, or Yarn version before pinning a Node version.
    NoPinnedNodeVersion {
        tool: String,
    },

    /// Thrown when the platform (Node version) could not be determined
    NoPlatform,

    /// Thrown when parsing the project manifest and there is a `"volta"` key without Node
    NoProjectNodeInManifest,

    /// Thrown when Yarn is not set in a project
    NoProjectYarn,

    /// Thrown when pnpm is not set in a project
    NoProjectPnpm,

    /// Thrown when no shell profiles could be found
    NoShellProfile {
        env_profile: String,
        bin_dir: PathBuf,
    },

    /// Thrown when the user tries to pin Node or Yarn versions outside of a package.
    NotInPackage,

    /// Thrown when default Yarn is not set
    NoDefaultYarn,

    /// Thrown when default pnpm is not set
    NoDefaultPnpm,

    /// Thrown when `npm link` is called with a package that isn't available
    NpmLinkMissingPackage {
        package: String,
    },

    /// Thrown when `npm link` is called with a package that was not installed / linked with npm
    NpmLinkWrongManager {
        package: String,
    },

    /// Thrown when there is no npm version matching the requested Semver/Tag
    NpmVersionNotFound {
        matching: String,
    },

    NpxNotAvailable {
        version: String,
    },

    /// Thrown when the command to install a global package is not successful
    PackageInstallFailed {
        package: String,
    },

    /// Thrown when parsing the package manifest fails
    PackageManifestParseError {
        package: String,
    },

    /// Thrown when reading the package manifest fails
    PackageManifestReadError {
        package: String,
    },

    /// Thrown when a specified package could not be found on the npm registry
    PackageNotFound {
        package: String,
    },

    /// Thrown when parsing a package manifest fails
    PackageParseError {
        file: PathBuf,
    },

    /// Thrown when reading a package manifest fails
    PackageReadError {
        file: PathBuf,
    },

    /// Thrown when a package has been unpacked but is not formed correctly.
    PackageUnpackError,

    /// Thrown when writing a package manifest fails
    PackageWriteError {
        file: PathBuf,
    },

    /// Thrown when unable to parse a bin config file
    ParseBinConfigError,

    /// Thrown when unable to parse a hooks.json file
    ParseHooksError {
        file: PathBuf,
    },

    /// Thrown when unable to parse the node index cache
    ParseNodeIndexCacheError,

    /// Thrown when unable to parse the node index
    ParseNodeIndexError {
        from_url: String,
    },

    /// Thrown when unable to parse the node index cache expiration
    ParseNodeIndexExpiryError,

    /// Thrown when unable to parse the npm manifest file from a node install
    ParseNpmManifestError,

    /// Thrown when unable to parse a package configuration
    ParsePackageConfigError,

    /// Thrown when unable to parse the platform.json file
    ParsePlatformError,

    /// Thrown when unable to parse a tool spec (`<tool>[@<version>]`)
    ParseToolSpecError {
        tool_spec: String,
    },

    /// Thrown when persisting an archive to the inventory fails
    PersistInventoryError {
        tool: String,
    },

    /// Thrown when there is no pnpm version matching a requested semver specifier.
    PnpmVersionNotFound {
        matching: String,
    },

    /// Thrown when executing a project-local binary fails
    ProjectLocalBinaryExecError {
        command: String,
    },

    /// Thrown when a project-local binary could not be found
    ProjectLocalBinaryNotFound {
        command: String,
    },

    /// Thrown when a publish hook contains both the url and bin fields
    PublishHookBothUrlAndBin,

    /// Thrown when a publish hook contains neither url nor bin fields
    PublishHookNeitherUrlNorBin,

    /// Thrown when there was an error reading the user bin directory
    ReadBinConfigDirError {
        dir: PathBuf,
    },

    /// Thrown when there was an error reading the config for a binary
    ReadBinConfigError {
        file: PathBuf,
    },

    /// Thrown when unable to read the default npm version file
    ReadDefaultNpmError {
        file: PathBuf,
    },

    /// Thrown when unable to read the contents of a directory
    ReadDirError {
        dir: PathBuf,
    },

    /// Thrown when there was an error opening a hooks.json file
    ReadHooksError {
        file: PathBuf,
    },

    /// Thrown when there was an error reading the Node Index Cache
    ReadNodeIndexCacheError {
        file: PathBuf,
    },

    /// Thrown when there was an error reading the Node Index Cache Expiration
    ReadNodeIndexExpiryError {
        file: PathBuf,
    },

    /// Thrown when there was an error reading the npm manifest file
    ReadNpmManifestError,

    /// Thrown when there was an error reading a package configuration file
    ReadPackageConfigError {
        file: PathBuf,
    },

    /// Thrown when there was an error opening the user platform file
    ReadPlatformError {
        file: PathBuf,
    },

    /// Thrown when unable to read the user Path environment variable from the registry
    #[cfg(windows)]
    ReadUserPathError,

    /// Thrown when the public registry for Node or Yarn could not be downloaded.
    RegistryFetchError {
        tool: String,
        from_url: String,
    },

    /// Thrown when the shim binary is called directly, not through a symlink
    RunShimDirectly,

    /// Thrown when there was an error setting a tool to executable
    SetToolExecutable {
        tool: String,
    },

    /// Thrown when there was an error copying an unpacked tool to the image directory
    SetupToolImageError {
        tool: String,
        version: String,
        dir: PathBuf,
    },

    /// Thrown when Volta is unable to create a shim
    ShimCreateError {
        name: String,
    },

    /// Thrown when Volta is unable to remove a shim
    ShimRemoveError {
        name: String,
    },

    /// Thrown when serializing a bin config to JSON fails
    StringifyBinConfigError,

    /// Thrown when serializing a package config to JSON fails
    StringifyPackageConfigError,

    /// Thrown when serializing the platform to JSON fails
    StringifyPlatformError,

    /// Thrown when a given feature has not yet been implemented
    Unimplemented {
        feature: String,
    },

    /// Thrown when unpacking an archive (tarball or zip) fails
    UnpackArchiveError {
        tool: String,
        version: String,
    },

    /// Thrown when a package to upgrade was not found
    UpgradePackageNotFound {
        package: String,
        manager: PackageManager,
    },

    /// Thrown when a package to upgrade was installed with a different package manager
    UpgradePackageWrongManager {
        package: String,
        manager: PackageManager,
    },

    VersionParseError {
        version: String,
    },

    /// Thrown when there was an error writing a bin config file
    WriteBinConfigError {
        file: PathBuf,
    },

    /// Thrown when there was an error writing the default npm to file
    WriteDefaultNpmError {
        file: PathBuf,
    },

    /// Thrown when there was an error writing the npm launcher
    WriteLauncherError {
        tool: String,
    },

    /// Thrown when there was an error writing the node index cache
    WriteNodeIndexCacheError {
        file: PathBuf,
    },

    /// Thrown when there was an error writing the node index expiration
    WriteNodeIndexExpiryError {
        file: PathBuf,
    },

    /// Thrown when there was an error writing a package config
    WritePackageConfigError {
        file: PathBuf,
    },

    /// Thrown when writing the platform.json file fails
    WritePlatformError {
        file: PathBuf,
    },

    /// Thrown when unable to write the user PATH environment variable
    #[cfg(windows)]
    WriteUserPathError,

    /// Thrown when a user attempts to install a version of Yarn2
    Yarn2NotSupported,

    /// Thrown when there is an error fetching the latest version of Yarn
    YarnLatestFetchError {
        from_url: String,
    },

    /// Thrown when there is no Yarn version matching a requested semver specifier.
    YarnVersionNotFound {
        matching: String,
    },
}

impl fmt::Display for ErrorKind {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match self {
            ErrorKind::BinaryAlreadyInstalled {
                bin_name,
                existing_package,
                new_package,
            } => write!(
                f,
                "Executable '{}' is already installed by {}

Please remove {} before installing {}",
                bin_name, existing_package, existing_package, new_package
            ),
            ErrorKind::BinaryExecError => write!(
                f,
                "Could not execute command.

See `volta help install` and `volta help pin` for info about making tools available."
            ),
            ErrorKind::BinaryNotFound { name } => write!(
                f,
                r#"Could not find executable "{}"

Use `volta install` to add a package to your toolchain (see `volta help install` for more info)."#,
                name
            ),
            ErrorKind::BuildPathError => write!(
                f,
                "Could not create execution environment.

Please ensure your PATH is valid."
            ),
            ErrorKind::BypassError { command } => write!(
                f,
                "Could not execute command '{}'

VOLTA_BYPASS is enabled, please ensure that the command exists on your system or unset VOLTA_BYPASS",
                command,
            ),
            ErrorKind::CannotFetchPackage { package } => write!(
                f,
                "Fetching packages without installing them is not supported.

Use `volta install {}` to update the default version.",
                package
            ),
            ErrorKind::CannotPinPackage { package } => write!(
                f,
                "Only node and yarn can be pinned in a project

Use `npm install` or `yarn add` to select a version of {} for this project.",
                package
            ),
            ErrorKind::CompletionsOutFileError { path } => write!(
                f,
                "Completions file `{}` already exists.

Please remove the file or pass `-f` or `--force` to override.",
                path.display()
            ),
            ErrorKind::ContainingDirError { path } => write!(
                f,
                "Could not create the containing directory for {}

{}",
                path.display(),
                PERMISSIONS_CTA
            ),
            ErrorKind::CouldNotDetermineTool => write!(
                f,
                "Could not determine tool name

{}",
                REPORT_BUG_CTA
            ),
            ErrorKind::CouldNotStartMigration => write!(
                f,
                "Could not start migration process to upgrade your Volta directory.

Please ensure you have 'volta-migrate' on your PATH and run it directly."
            ),
            ErrorKind::CreateDirError { dir } => write!(
                f,
                "Could not create directory {}

Please ensure that you have the correct permissions.",
                dir.display()
            ),
            ErrorKind::CreateLayoutFileError { file } => write!(
                f,
                "Could not create layout file {}

{}",
                file.display(), PERMISSIONS_CTA
            ),
            ErrorKind::CreateSharedLinkError { name } => write!(
                f,
                "Could not create shared environment for package '{}'

{}",
                name, PERMISSIONS_CTA
            ),
            ErrorKind::CreateTempDirError { in_dir } => write!(
                f,
                "Could not create temporary directory
in {}

{}",
                in_dir.display(),
                PERMISSIONS_CTA
            ),
            ErrorKind::CreateTempFileError { in_dir } => write!(
                f,
                "Could not create temporary file
in {}

{}",
                in_dir.display(),
                PERMISSIONS_CTA
            ),
            ErrorKind::CurrentDirError => write!(
                f,
                "Could not determine current directory

Please ensure that you have the correct permissions."
            ),
            ErrorKind::DeleteDirectoryError { directory } => write!(
                f,
                "Could not remove directory
at {}

{}",
                directory.display(),
                PERMISSIONS_CTA
            ),
            ErrorKind::DeleteFileError { file } => write!(
                f,
                "Could not remove file
at {}

{}",
                file.display(),
                PERMISSIONS_CTA
            ),
            ErrorKind::DeprecatedCommandError { command, advice } => {
                write!(f, "The subcommand `{}` is deprecated.\n{}", command, advice)
            }
            ErrorKind::DownloadToolNetworkError { tool, from_url } => write!(
                f,
                "Could not download {}
from {}

Please verify your internet connection and ensure the correct version is specified.",
                tool, from_url
            ),
            ErrorKind::ExecuteHookError { command } => write!(
                f,
                "Could not execute hook command: '{}'

Please ensure that the correct command is specified.",
                command
            ),
            ErrorKind::ExtensionCycleError { paths, duplicate } => {
                // Detected infinite loop in project workspace:
                //
                // --> /home/user/workspace/project/package.json
                //     /home/user/workspace/package.json
                // --> /home/user/workspace/project/package.json
                //
                // Please ensure that project workspaces do not depend on each other.
                f.write_str("Detected infinite loop in project workspace:\n\n")?;

                for path in paths {
                    if path == duplicate {
                        f.write_str("--> ")?;
                    } else {
                        f.write_str("    ")?;
                    }

                    writeln!(f, "{}", path.display())?;
                }

                writeln!(f, "--> {}", duplicate.display())?;
                writeln!(f)?;

                f.write_str("Please ensure that project workspaces do not depend on each other.")
            }
            ErrorKind::ExtensionPathError { path } => write!(
                f,
                "Could not determine path to project workspace: '{}'

Please ensure that the file exists and is accessible.",
                path.display(),
            ),
            ErrorKind::HookCommandFailed { command } => write!(
                f,
                "Hook command '{}' indicated a failure.

Please verify the requested tool and version.",
                command
            ),
            ErrorKind::HookMultipleFieldsSpecified => write!(
                f,
                "Hook configuration includes multiple hook types.

Please include only one of 'bin', 'prefix', or 'template'"
            ),
            ErrorKind::HookNoFieldsSpecified => write!(
                f,
                "Hook configuration includes no hook types.

Please include one of 'bin', 'prefix', or 'template'"
            ),
            ErrorKind::HookPathError { command } => write!(
                f,
                "Could not determine path to hook command: '{}'

Please ensure that the correct command is specified.",
                command
            ),
            ErrorKind::InstalledPackageNameError => write!(
                f,
                "Could not determine the name of the package that was just installed.

{}",
                REPORT_BUG_CTA
            ),
            ErrorKind::InvalidHookCommand { command } => write!(
                f,
                "Invalid hook command: '{}'

Please ensure that the correct command is specified.",
                command
            ),
            ErrorKind::InvalidHookOutput { command } => write!(
                f,
                "Could not read output from hook command: '{}'

Please ensure that the command output is valid UTF-8 text.",
                command
            ),

            ErrorKind::InvalidInvocation {
                action,
                name,
                version,
            } => {
                let error = format!(
                    "`volta {action} {name} {version}` is not supported.",
                    action = action,
                    name = name,
                    version = version
                );

                let call_to_action = format!(
"To {action} '{name}' version '{version}', please run `volta {action} {formatted}`. \
To {action} the packages '{name}' and '{version}', please {action} them in separate commands, or with explicit versions.",
                    action=action,
                    name=name,
                    version=version,
                    formatted=tool_version(name, version)
                );

                let wrapped_cta = match text_width() {
                    Some(width) => fill(&call_to_action, width),
                    None => call_to_action,
                };

                write!(f, "{}\n\n{}", error, wrapped_cta)
            }

            ErrorKind::InvalidInvocationOfBareVersion {
                action,
                version,
            } => {
                let error = format!(
                    "`volta {action} {version}` is not supported.",
                    action = action,
                    version = version
                );

                let call_to_action = format!(
"To {action} node version '{version}', please run `volta {action} {formatted}`. \
To {action} the package '{version}', please use an explicit version such as '{version}@latest'.",
                    action=action,
                    version=version,
                    formatted=tool_version("node", version)
                );

                let wrapped_cta = match text_width() {
                    Some(width) => fill(&call_to_action, width),
                    None => call_to_action,
                };

                write!(f, "{}\n\n{}", error, wrapped_cta)
            }

            ErrorKind::InvalidRegistryFormat { format } => write!(
                f,
                "Unrecognized index registry format: '{}'

Please specify either 'npm' or 'github' for the format.",
format
            ),

            ErrorKind::InvalidToolName { name, errors } => {
                let indentation = "    ";
                let wrapped = match text_width() {
                    Some(width) => fill(&errors.join("\n"), width - indentation.len()),
                    None => errors.join("\n"),
                };
                let formatted_errs = indent(&wrapped, indentation);

                let call_to_action = if errors.len() > 1 {
                    "Please fix the following errors:"
                } else {
                    "Please fix the following error:"
                };

                write!(
                    f,
                    "Invalid tool name `{}`\n\n{}\n{}",
                    name, call_to_action, formatted_errs
                )
            }
            // Note: No CTA as this error is purely informational and shouldn't be exposed to the user
            ErrorKind::LockAcquireError => write!(
                f,
                "Unable to acquire lock on Volta directory"
            ),
            ErrorKind::NoBundledNpm { command } => write!(
                f,
                "Could not detect bundled npm version.

Please ensure you have a Node version selected with `volta {} node` (see `volta help {0}` for more info).",
                command
            ),
            ErrorKind::NoCommandLinePnpm => write!(
                f,
                "No pnpm version specified.

Use `volta run --pnpm` to select a version (see `volta help run` for more info)."
            ),
            ErrorKind::NoCommandLineYarn => write!(
                f,
                "No Yarn version specified.

Use `volta run --yarn` to select a version (see `volta help run` for more info)."
            ),
            ErrorKind::NoDefaultNodeVersion { tool } => write!(
                f,
                "Cannot install {} because the default Node version is not set.

Use `volta install node` to select a default Node first, then install a {0} version.",
                                tool
            ),
            ErrorKind::NodeVersionNotFound { matching } => write!(
                f,
                r#"Could not find Node version matching "{}" in the version registry.

Please verify that the version is correct."#,
                matching
            ),
            ErrorKind::NoHomeEnvironmentVar => write!(
                f,
                "Could not determine home directory.

Please ensure the environment variable 'HOME' is set."
            ),
            ErrorKind::NoInstallDir => write!(
                f,
                "Could not determine Volta install directory.

Please ensure Volta was installed correctly"
            ),
            ErrorKind::NoLocalDataDir => write!(
                f,
                "Could not determine LocalAppData directory.

Please ensure the directory is available."
            ),
            ErrorKind::NoPinnedNodeVersion { tool } => write!(
                f,
                "Cannot pin {} because the Node version is not pinned in this project.

Use `volta pin node` to pin Node first, then pin a {0} version.",
                tool
            ),
            ErrorKind::NoPlatform => write!(
                f,
                "Node is not available.

To run any Node command, first set a default version using `volta install node`"
            ),
            ErrorKind::NoProjectNodeInManifest => write!(
                f,
                "No Node version found in this project.

Use `volta pin node` to select a version (see `volta help pin` for more info)."
            ),
            ErrorKind::NoProjectPnpm => write!(
                f,
                "No pnpm version found in this project.

Use `volta pin pnpm` to select a version (see `volta help pin` for more info)."
            ),
            ErrorKind::NoProjectYarn => write!(
                f,
                "No Yarn version found in this project.

Use `volta pin yarn` to select a version (see `volta help pin` for more info)."
            ),
            ErrorKind::NoShellProfile { env_profile, bin_dir } => write!(
                f,
                "Could not locate user profile.
Tried $PROFILE ({}), ~/.bashrc, ~/.bash_profile, ~/.zshenv ~/.zshrc, ~/.profile, and ~/.config/fish/config.fish

Please create one of these and try again; or you can edit your profile manually to add '{}' to your PATH",
                env_profile, bin_dir.display()
            ),
            ErrorKind::NotInPackage => write!(
                f,
                "Not in a node package.

Use `volta install` to select a default version of a tool."
            ),
            ErrorKind::NoDefaultPnpm => write!(
                f,
                "pnpm is not available.

Use `volta install pnpm` to select a default version (see `volta help install` for more info)."
            ),
            ErrorKind::NoDefaultYarn => write!(
                f,
                "Yarn is not available.

Use `volta install yarn` to select a default version (see `volta help install` for more info)."
            ),
            ErrorKind::NpmLinkMissingPackage { package } => write!(
                f,
                "Could not locate the package '{}'

Please ensure it is available by running `npm link` in its source directory.",
                package
            ),
            ErrorKind::NpmLinkWrongManager { package } => write!(
                f,
                "The package '{}' was not installed using npm and cannot be linked with `npm link`

Please ensure it is linked with `npm link` or installed with `npm i -g {0}`.",
                package
            ),
            ErrorKind::NpmVersionNotFound { matching } => write!(
                f,
                r#"Could not find Node version matching "{}" in the version registry.

Please verify that the version is correct."#,
                matching
            ),
            ErrorKind::NpxNotAvailable { version } => write!(
                f,
                "'npx' is only available with npm >= 5.2.0

This project is configured to use version {} of npm.",
                version
            ),
            ErrorKind::PackageInstallFailed { package } => write!(
                f,
                "Could not install package '{}'

Please confirm the package is valid and run with `--verbose` for more diagnostics.",
                package
            ),
            ErrorKind::PackageManifestParseError { package } => write!(
                f,
                "Could not parse package.json manifest for {}

Please ensure the package includes a valid manifest file.",
                package
            ),
            ErrorKind::PackageManifestReadError { package } => write!(
                f,
                "Could not read package.json manifest for {}

Please ensure the package includes a valid manifest file.",
                package
            ),
            ErrorKind::PackageNotFound { package } => write!(
                f,
                "Could not find '{}' in the package registry.

Please verify the requested package is correct.",
                package
            ),
            ErrorKind::PackageParseError { file } => write!(
                f,
                "Could not parse project manifest
at {}

Please ensure that the file is correctly formatted.",
                file.display()
            ),
            ErrorKind::PackageReadError { file } => write!(
                f,
                "Could not read project manifest
from {}

Please ensure that the file exists.",
                file.display()
            ),
            ErrorKind::PackageUnpackError => write!(
                f,
                "Could not determine package directory layout.

Please ensure the package is correctly formatted."
            ),
            ErrorKind::PackageWriteError { file } => write!(
                f,
                "Could not write project manifest
to {}

Please ensure you have correct permissions.",
                file.display()
            ),
            ErrorKind::ParseBinConfigError => write!(
                f,
                "Could not parse executable configuration file.

{}",
                REPORT_BUG_CTA
            ),
            ErrorKind::ParseHooksError { file } => write!(
                f,
                "Could not parse hooks configuration file.
from {}

Please ensure the file is correctly formatted.",
                file.display()
            ),
            ErrorKind::ParseNodeIndexCacheError => write!(
                f,
                "Could not parse Node index cache file.

{}",
                REPORT_BUG_CTA
            ),
            ErrorKind::ParseNodeIndexError { from_url } => write!(
                f,
                "Could not parse Node version index
from {}

Please verify your internet connection.",
                from_url
            ),
            ErrorKind::ParseNodeIndexExpiryError => write!(
                f,
                "Could not parse Node index cache expiration file.

{}",
                REPORT_BUG_CTA
            ),
            ErrorKind::ParseNpmManifestError => write!(
                f,
                "Could not parse package.json file for bundled npm.

Please ensure the version of Node is correct."
            ),
            ErrorKind::ParsePackageConfigError => write!(
                f,
                "Could not parse package configuration file.

{}",
                REPORT_BUG_CTA
            ),
            ErrorKind::ParsePlatformError => write!(
                f,
                "Could not parse platform settings file.

{}",
                REPORT_BUG_CTA
            ),
            ErrorKind::ParseToolSpecError { tool_spec } => write!(
                f,
                "Could not parse tool spec `{}`

Please supply a spec in the format `<tool name>[@<version>]`.",
                tool_spec
            ),
            ErrorKind::PersistInventoryError { tool } => write!(
                f,
                "Could not store {} archive in inventory cache

{}",
                tool, PERMISSIONS_CTA
            ),
            ErrorKind::PnpmVersionNotFound { matching } => write!(
                f,
                r#"Could not find pnpm version matching "{}" in the version registry.

Please verify that the version is correct."#,
                matching
            ),
            ErrorKind::ProjectLocalBinaryExecError { command } => write!(
                f,
                "Could not execute `{}`

Please ensure you have correct permissions to access the file.",
                command
            ),
            ErrorKind::ProjectLocalBinaryNotFound { command } => write!(
                f,
                "Could not locate executable `{}` in your project.

Please ensure that all project dependencies are installed with `npm install` or `yarn install`",
                command
            ),
            ErrorKind::PublishHookBothUrlAndBin => write!(
                f,
                "Publish hook configuration includes both hook types.

Please include only one of 'bin' or 'url'"
            ),
            ErrorKind::PublishHookNeitherUrlNorBin => write!(
                f,
                "Publish hook configuration includes no hook types.

Please include one of 'bin' or 'url'"
            ),
            ErrorKind::ReadBinConfigDirError { dir } => write!(
                f,
                "Could not read executable metadata directory
at {}

{}",
                dir.display(),
                PERMISSIONS_CTA
            ),
            ErrorKind::ReadBinConfigError { file } => write!(
                f,
                "Could not read executable configuration
from {}

{}",
                file.display(),
                PERMISSIONS_CTA
            ),
            ErrorKind::ReadDefaultNpmError { file } => write!(
                f,
                "Could not read default npm version
from {}

{}",
                file.display(),
                PERMISSIONS_CTA
            ),
            ErrorKind::ReadDirError { dir } => write!(
                f,
                "Could not read contents from directory {}

{}",
                dir.display(), PERMISSIONS_CTA
            ),
            ErrorKind::ReadHooksError { file } => write!(
                f,
                "Could not read hooks file
from {}

{}",
                file.display(),
                PERMISSIONS_CTA
            ),
            ErrorKind::ReadNodeIndexCacheError { file } => write!(
                f,
                "Could not read Node index cache
from {}

{}",
                file.display(),
                PERMISSIONS_CTA
            ),
            ErrorKind::ReadNodeIndexExpiryError { file } => write!(
                f,
                "Could not read Node index cache expiration
from {}

{}",
                file.display(),
                PERMISSIONS_CTA
            ),
            ErrorKind::ReadNpmManifestError => write!(
                f,
                "Could not read package.json file for bundled npm.

Please ensure the version of Node is correct."
            ),
            ErrorKind::ReadPackageConfigError { file } => write!(
                f,
                "Could not read package configuration file
from {}

{}",
                file.display(),
                PERMISSIONS_CTA
            ),
            ErrorKind::ReadPlatformError { file } => write!(
                f,
                "Could not read default platform file
from {}

{}",
                file.display(),
                PERMISSIONS_CTA
            ),
            #[cfg(windows)]
            ErrorKind::ReadUserPathError => write!(
                f,
                "Could not read user Path environment variable.

Please ensure you have access to the your environment variables."
            ),
            ErrorKind::RegistryFetchError { tool, from_url } => write!(
                f,
                "Could not download {} version registry
from {}

Please verify your internet connection.",
                tool, from_url
            ),
            ErrorKind::RunShimDirectly => write!(
                f,
                "'volta-shim' should not be called directly.

Please use the existing shims provided by Volta (node, yarn, etc.) to run tools."
            ),
            ErrorKind::SetToolExecutable { tool } => write!(
                f,
                r#"Could not set "{}" to executable

{}"#,
                tool, PERMISSIONS_CTA
            ),
            ErrorKind::SetupToolImageError { tool, version, dir } => write!(
                f,
                "Could not create environment for {} v{}
at {}

{}",
                tool,
                version,
                dir.display(),
                PERMISSIONS_CTA
            ),
            ErrorKind::ShimCreateError { name } => write!(
                f,
                r#"Could not create shim for "{}"

{}"#,
                name, PERMISSIONS_CTA
            ),
            ErrorKind::ShimRemoveError { name } => write!(
                f,
                r#"Could not remove shim for "{}"

{}"#,
                name, PERMISSIONS_CTA
            ),
            ErrorKind::StringifyBinConfigError => write!(
                f,
                "Could not serialize executable configuration.

{}",
                REPORT_BUG_CTA
            ),
            ErrorKind::StringifyPackageConfigError => write!(
                f,
                "Could not serialize package configuration.

{}",
                REPORT_BUG_CTA
            ),
            ErrorKind::StringifyPlatformError => write!(
                f,
                "Could not serialize platform settings.

{}",
                REPORT_BUG_CTA
            ),
            ErrorKind::Unimplemented { feature } => {
                write!(f, "{} is not supported yet.", feature)
            }
            ErrorKind::UnpackArchiveError { tool, version } => write!(
                f,
                "Could not unpack {} v{}

Please ensure the correct version is specified.",
                tool, version
            ),
            ErrorKind::UpgradePackageNotFound { package, manager } => write!(
                f,
                r#"Could not locate the package '{}' to upgrade.

Please ensure it is installed with `{} {0}`"#,
                package,
                match manager {
                    PackageManager::Npm => "npm i -g",
                    PackageManager::Pnpm => "pnpm add -g",
                    PackageManager::Yarn => "yarn global add",
                }
            ),
            ErrorKind::UpgradePackageWrongManager { package, manager } => {
                let (name, command) = match manager {
                    PackageManager::Npm => ("npm", "npm update -g"),
                    PackageManager::Pnpm => ("pnpm", "pnpm update -g"),
                    PackageManager::Yarn => ("Yarn", "yarn global upgrade"),
                };
                write!(
                    f,
                    r#"The package '{}' was installed using {}.

To upgrade it, please use the command `{} {0}`"#,
                    package, name, command
                )
            }
            ErrorKind::VersionParseError { version } => write!(
                f,
                r#"Could not parse version "{}"

Please verify the intended version."#,
                version
            ),
            ErrorKind::WriteBinConfigError { file } => write!(
                f,
                "Could not write executable configuration
to {}

{}",
                file.display(),
                PERMISSIONS_CTA
            ),
            ErrorKind::WriteDefaultNpmError { file } => write!(
                f,
                "Could not write bundled npm version
to {}

{}",
                file.display(),
                PERMISSIONS_CTA
            ),
            ErrorKind::WriteLauncherError { tool } => write!(
                f,
                "Could not set up launcher for {}

This is most likely an intermittent failure, please try again.",
                tool
            ),
            ErrorKind::WriteNodeIndexCacheError { file } => write!(
                f,
                "Could not write Node index cache
to {}

{}",
                file.display(),
                PERMISSIONS_CTA
            ),
            ErrorKind::WriteNodeIndexExpiryError { file } => write!(
                f,
                "Could not write Node index cache expiration
to {}

{}",
                file.display(),
                PERMISSIONS_CTA
            ),
            ErrorKind::WritePackageConfigError { file } => write!(
                f,
                "Could not write package configuration
to {}

{}",
                file.display(),
                PERMISSIONS_CTA
            ),
            ErrorKind::WritePlatformError { file } => write!(
                f,
                "Could not save platform settings
to {}

{}",
                file.display(),
                PERMISSIONS_CTA
            ),
            #[cfg(windows)]
            ErrorKind::WriteUserPathError => write!(
                f,
                "Could not write Path environment variable.

Please ensure you have permissions to edit your environment variables."
            ),
            ErrorKind::Yarn2NotSupported => write!(
                f,
                "Yarn version 2 is not recommended for use, and not supported by Volta.

Please use version 3 or greater instead."
            ),
            ErrorKind::YarnLatestFetchError { from_url } => write!(
                f,
                "Could not fetch latest version of Yarn
from {}

Please verify your internet connection.",
                from_url
            ),
            ErrorKind::YarnVersionNotFound { matching } => write!(
                f,
                r#"Could not find Yarn version matching "{}" in the version registry.

Please verify that the version is correct."#,
                matching
            ),
        }
    }
}

impl ErrorKind {
    pub fn exit_code(&self) -> ExitCode {
        match self {
            ErrorKind::BinaryAlreadyInstalled { .. } => ExitCode::FileSystemError,
            ErrorKind::BinaryExecError => ExitCode::ExecutionFailure,
            ErrorKind::BinaryNotFound { .. } => ExitCode::ExecutableNotFound,
            ErrorKind::BuildPathError => ExitCode::EnvironmentError,
            ErrorKind::BypassError { .. } => ExitCode::ExecutionFailure,
            ErrorKind::CannotFetchPackage { .. } => ExitCode::InvalidArguments,
            ErrorKind::CannotPinPackage { .. } => ExitCode::InvalidArguments,
            ErrorKind::CompletionsOutFileError { .. } => ExitCode::InvalidArguments,
            ErrorKind::ContainingDirError { .. } => ExitCode::FileSystemError,
            ErrorKind::CouldNotDetermineTool => ExitCode::UnknownError,
            ErrorKind::CouldNotStartMigration => ExitCode::EnvironmentError,
            ErrorKind::CreateDirError { .. } => ExitCode::FileSystemError,
            ErrorKind::CreateLayoutFileError { .. } => ExitCode::FileSystemError,
            ErrorKind::CreateSharedLinkError { .. } => ExitCode::FileSystemError,
            ErrorKind::CreateTempDirError { .. } => ExitCode::FileSystemError,
            ErrorKind::CreateTempFileError { .. } => ExitCode::FileSystemError,
            ErrorKind::CurrentDirError => ExitCode::EnvironmentError,
            ErrorKind::DeleteDirectoryError { .. } => ExitCode::FileSystemError,
            ErrorKind::DeleteFileError { .. } => ExitCode::FileSystemError,
            ErrorKind::DeprecatedCommandError { .. } => ExitCode::InvalidArguments,
            ErrorKind::DownloadToolNetworkError { .. } => ExitCode::NetworkError,
            ErrorKind::ExecuteHookError { .. } => ExitCode::ExecutionFailure,
            ErrorKind::ExtensionCycleError { .. } => ExitCode::ConfigurationError,
            ErrorKind::ExtensionPathError { .. } => ExitCode::FileSystemError,
            ErrorKind::HookCommandFailed { .. } => ExitCode::ConfigurationError,
            ErrorKind::HookMultipleFieldsSpecified => ExitCode::ConfigurationError,
            ErrorKind::HookNoFieldsSpecified => ExitCode::ConfigurationError,
            ErrorKind::HookPathError { .. } => ExitCode::ConfigurationError,
            ErrorKind::InstalledPackageNameError => ExitCode::UnknownError,
            ErrorKind::InvalidHookCommand { .. } => ExitCode::ExecutableNotFound,
            ErrorKind::InvalidHookOutput { .. } => ExitCode::ExecutionFailure,
            ErrorKind::InvalidInvocation { .. } => ExitCode::InvalidArguments,
            ErrorKind::InvalidInvocationOfBareVersion { .. } => ExitCode::InvalidArguments,
            ErrorKind::InvalidRegistryFormat { .. } => ExitCode::ConfigurationError,
            ErrorKind::InvalidToolName { .. } => ExitCode::InvalidArguments,
            ErrorKind::LockAcquireError => ExitCode::FileSystemError,
            ErrorKind::NoBundledNpm { .. } => ExitCode::ConfigurationError,
            ErrorKind::NoCommandLinePnpm => ExitCode::ConfigurationError,
            ErrorKind::NoCommandLineYarn => ExitCode::ConfigurationError,
            ErrorKind::NoDefaultNodeVersion { .. } => ExitCode::ConfigurationError,
            ErrorKind::NodeVersionNotFound { .. } => ExitCode::NoVersionMatch,
            ErrorKind::NoHomeEnvironmentVar => ExitCode::EnvironmentError,
            ErrorKind::NoInstallDir => ExitCode::EnvironmentError,
            ErrorKind::NoLocalDataDir => ExitCode::EnvironmentError,
            ErrorKind::NoPinnedNodeVersion { .. } => ExitCode::ConfigurationError,
            ErrorKind::NoPlatform => ExitCode::ConfigurationError,
            ErrorKind::NoProjectNodeInManifest => ExitCode::ConfigurationError,
            ErrorKind::NoProjectPnpm => ExitCode::ConfigurationError,
            ErrorKind::NoProjectYarn => ExitCode::ConfigurationError,
            ErrorKind::NoShellProfile { .. } => ExitCode::EnvironmentError,
            ErrorKind::NotInPackage => ExitCode::ConfigurationError,
            ErrorKind::NoDefaultPnpm => ExitCode::ConfigurationError,
            ErrorKind::NoDefaultYarn => ExitCode::ConfigurationError,
            ErrorKind::NpmLinkMissingPackage { .. } => ExitCode::ConfigurationError,
            ErrorKind::NpmLinkWrongManager { .. } => ExitCode::ConfigurationError,
            ErrorKind::NpmVersionNotFound { .. } => ExitCode::NoVersionMatch,
            ErrorKind::NpxNotAvailable { .. } => ExitCode::ExecutableNotFound,
            ErrorKind::PackageInstallFailed { .. } => ExitCode::UnknownError,
            ErrorKind::PackageManifestParseError { .. } => ExitCode::ConfigurationError,
            ErrorKind::PackageManifestReadError { .. } => ExitCode::FileSystemError,
            ErrorKind::PackageNotFound { .. } => ExitCode::InvalidArguments,
            ErrorKind::PackageParseError { .. } => ExitCode::ConfigurationError,
            ErrorKind::PackageReadError { .. } => ExitCode::FileSystemError,
            ErrorKind::PackageUnpackError => ExitCode::ConfigurationError,
            ErrorKind::PackageWriteError { .. } => ExitCode::FileSystemError,
            ErrorKind::ParseBinConfigError => ExitCode::UnknownError,
            ErrorKind::ParseHooksError { .. } => ExitCode::ConfigurationError,
            ErrorKind::ParseToolSpecError { .. } => ExitCode::InvalidArguments,
            ErrorKind::ParseNodeIndexCacheError => ExitCode::UnknownError,
            ErrorKind::ParseNodeIndexError { .. } => ExitCode::NetworkError,
            ErrorKind::ParseNodeIndexExpiryError => ExitCode::UnknownError,
            ErrorKind::ParseNpmManifestError => ExitCode::UnknownError,
            ErrorKind::ParsePackageConfigError => ExitCode::UnknownError,
            ErrorKind::ParsePlatformError => ExitCode::ConfigurationError,
            ErrorKind::PersistInventoryError { .. } => ExitCode::FileSystemError,
            ErrorKind::PnpmVersionNotFound { .. } => ExitCode::NoVersionMatch,
            ErrorKind::ProjectLocalBinaryExecError { .. } => ExitCode::ExecutionFailure,
            ErrorKind::ProjectLocalBinaryNotFound { .. } => ExitCode::FileSystemError,
            ErrorKind::PublishHookBothUrlAndBin => ExitCode::ConfigurationError,
            ErrorKind::PublishHookNeitherUrlNorBin => ExitCode::ConfigurationError,
            ErrorKind::ReadBinConfigDirError { .. } => ExitCode::FileSystemError,
            ErrorKind::ReadBinConfigError { .. } => ExitCode::FileSystemError,
            ErrorKind::ReadDefaultNpmError { .. } => ExitCode::FileSystemError,
            ErrorKind::ReadDirError { .. } => ExitCode::FileSystemError,
            ErrorKind::ReadHooksError { .. } => ExitCode::FileSystemError,
            ErrorKind::ReadNodeIndexCacheError { .. } => ExitCode::FileSystemError,
            ErrorKind::ReadNodeIndexExpiryError { .. } => ExitCode::FileSystemError,
            ErrorKind::ReadNpmManifestError => ExitCode::UnknownError,
            ErrorKind::ReadPackageConfigError { .. } => ExitCode::FileSystemError,
            ErrorKind::ReadPlatformError { .. } => ExitCode::FileSystemError,
            #[cfg(windows)]
            ErrorKind::ReadUserPathError => ExitCode::EnvironmentError,
            ErrorKind::RegistryFetchError { .. } => ExitCode::NetworkError,
            ErrorKind::RunShimDirectly => ExitCode::InvalidArguments,
            ErrorKind::SetupToolImageError { .. } => ExitCode::FileSystemError,
            ErrorKind::SetToolExecutable { .. } => ExitCode::FileSystemError,
            ErrorKind::ShimCreateError { .. } => ExitCode::FileSystemError,
            ErrorKind::ShimRemoveError { .. } => ExitCode::FileSystemError,
            ErrorKind::StringifyBinConfigError => ExitCode::UnknownError,
            ErrorKind::StringifyPackageConfigError => ExitCode::UnknownError,
            ErrorKind::StringifyPlatformError => ExitCode::UnknownError,
            ErrorKind::Unimplemented { .. } => ExitCode::UnknownError,
            ErrorKind::UnpackArchiveError { .. } => ExitCode::UnknownError,
            ErrorKind::UpgradePackageNotFound { .. } => ExitCode::ConfigurationError,
            ErrorKind::UpgradePackageWrongManager { .. } => ExitCode::ConfigurationError,
            ErrorKind::VersionParseError { .. } => ExitCode::NoVersionMatch,
            ErrorKind::WriteBinConfigError { .. } => ExitCode::FileSystemError,
            ErrorKind::WriteDefaultNpmError { .. } => ExitCode::FileSystemError,
            ErrorKind::WriteLauncherError { .. } => ExitCode::FileSystemError,
            ErrorKind::WriteNodeIndexCacheError { .. } => ExitCode::FileSystemError,
            ErrorKind::WriteNodeIndexExpiryError { .. } => ExitCode::FileSystemError,
            ErrorKind::WritePackageConfigError { .. } => ExitCode::FileSystemError,
            ErrorKind::WritePlatformError { .. } => ExitCode::FileSystemError,
            #[cfg(windows)]
            ErrorKind::WriteUserPathError => ExitCode::EnvironmentError,
            ErrorKind::Yarn2NotSupported => ExitCode::NoVersionMatch,
            ErrorKind::YarnLatestFetchError { .. } => ExitCode::NetworkError,
            ErrorKind::YarnVersionNotFound { .. } => ExitCode::NoVersionMatch,
        }
    }
}


================================================
FILE: crates/volta-core/src/error/mod.rs
================================================
use std::error::Error;
use std::fmt;
use std::process::exit;

mod kind;
mod reporter;

pub use kind::ErrorKind;
pub use reporter::report_error;

pub type Fallible<T> = Result<T, VoltaError>;

/// Error type for Volta
#[derive(Debug)]
pub struct VoltaError {
    inner: Box<Inner>,
}

#[derive(Debug)]
struct Inner {
    kind: ErrorKind,
    source: Option<Box<dyn Error>>,
}

impl VoltaError {
    /// The exit code Volta should use when this error stops execution
    pub fn exit_code(&self) -> ExitCode {
        self.inner.kind.exit_code()
    }

    /// Create a new VoltaError instance including a source error
    pub fn from_source<E>(source: E, kind: ErrorKind) -> Self
    where
        E: Into<Box<dyn Error>>,
    {
        VoltaError {
            inner: Box::new(Inner {
                kind,
                source: Some(source.into()),
            }),
        }
    }

    /// Get a reference to the ErrorKind for this error
    pub fn kind(&self) -> &ErrorKind {
        &self.inner.kind
    }
}

impl fmt::Display for VoltaError {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        self.inner.kind.fmt(f)
    }
}

impl Error for VoltaError {
    fn source(&self) -> Option<&(dyn Error + 'static)> {
        self.inner.source.as_ref().map(|b| b.as_ref())
    }
}

impl From<ErrorKind> for VoltaError {
    fn from(kind: ErrorKind) -> Self {
        VoltaError {
            inner: Box::new(Inner { kind, source: None }),
        }
    }
}

/// Trait providing the with_context method to easily convert any Result error into a VoltaError
pub trait Context<T> {
    fn with_context<F>(self, f: F) -> Fallible<T>
    where
        F: FnOnce() -> ErrorKind;
}

impl<T, E> Context<T> for Result<T, E>
where
    E: Error + 'static,
{
    fn with_context<F>(self, f: F) -> Fallible<T>
    where
        F: FnOnce() -> ErrorKind,
    {
        self.map_err(|e| VoltaError::from_source(e, f()))
    }
}

/// Exit codes supported by Volta Errors
#[derive(Copy, Clone, Debug)]
pub enum ExitCode {
    /// No error occurred.
    Success = 0,

    /// An unknown error occurred.
    UnknownError = 1,

    /// An invalid combination of command-line arguments was supplied.
    InvalidArguments = 3,

    /// No match could be found for the requested version string.
    NoVersionMatch = 4,

    /// A network error occurred.
    NetworkError = 5,

    /// A required environment variable was unset or invalid.
    EnvironmentError = 6,

    /// A file could not be read or written.
    FileSystemError = 7,

    /// Package configuration is missing or incorrect.
    ConfigurationError = 8,

    /// The command or feature is not yet implemented.
    NotYetImplemented = 9,

    /// The requested executable could not be run.
    ExecutionFailure = 126,

    /// The requested executable is not available.
    ExecutableNotFound = 127,
}

impl ExitCode {
    pub fn exit(self) -> ! {
        exit(self as i32);
    }
}


================================================
FILE: crates/volta-core/src/error/reporter.rs
================================================
use std::env::args_os;
use std::error::Error;
use std::fs::File;
use std::io::Write;
use std::path::PathBuf;

use super::VoltaError;
use crate::layout::volta_home;
use crate::style::format_error_cause;
use chrono::Local;
use ci_info::is_ci;
use console::strip_ansi_codes;
use fs_utils::ensure_containing_dir_exists;
use log::{debug, error};

/// Report an error, both to the console and to error logs
pub fn report_error(volta_version: &str, err: &VoltaError) {
    let message = err.to_string();
    error!("{}", message);

    if let Some(details) = compose_error_details(err) {
        if is_ci() {
            // In CI, we write the error details to the log so that they are available in the CI logs
            // A log file may not even exist by the time the user is reviewing a failure
            error!("{}", details);
        } else {
            // Outside of CI, we write the error details as Debug (Verbose) information
            // And we write an actual error log that the user can review
            debug!("{}", details);

            // Note: Writing the error log info directly to stderr as it is a message for the user
            // Any custom logs will have all of the details already, so showing a message about writing
            // the error log would be redundant
            match write_error_log(volta_version, message, details) {
                Ok(log_file) => {
                    eprintln!("Error details written to {}", log_file.to_string_lossy());
                }
                Err(_) => {
                    eprintln!("Unable to write error log!");
                }
            }
        }
    }
}

/// Write an error log with all details about the error
fn write_error_log(
    volta_version: &str,
    message: String,
    details: String,
) -> Result<PathBuf, Box<dyn Error>> {
    let file_name = Local::now()
        .format("volta-error-%Y-%m-%d_%H_%M_%S%.3f.log")
        .to_string();
    let log_file_path = volta_home()?.log_dir().join(file_name);

    ensure_containing_dir_exists(&log_file_path)?;
    let mut log_file = File::create(&log_file_path)?;

    writeln!(log_file, "{}", collect_arguments())?;
    writeln!(log_file, "Volta v{}", volta_version)?;
    writeln!(log_file)?;
    writeln!(log_file, "{}", strip_ansi_codes(&message))?;
    writeln!(log_file)?;
    writeln!(log_file, "{}", strip_ansi_codes(&details))?;

    Ok(log_file_path)
}

fn compose_error_details(err: &VoltaError) -> Option<String> {
    // Only compose details if there is an underlying cause for the error
    let mut current = err.source()?;
    let mut details = String::new();

    // Walk up the tree of causes and include all of them
    loop {
        details.push_str(&format_error_cause(current));

        match current.source() {
            Some(cause) => {
                details.push_str("\n\n");
                current = cause;
            }
            None => {
                break;
            }
        };
    }

    Some(details)
}

/// Combines all the arguments into a single String
fn collect_arguments() -> String {
    // The Debug formatter for OsString properly quotes and escapes each value
    args_os()
        .map(|arg| format!("{:?}", arg))
        .collect::<Vec<String>>()
        .join(" ")
}


================================================
FILE: crates/volta-core/src/event.rs
================================================
//! Events for the sessions in executables and shims and everything

use std::env;
use std::time::{SystemTime, UNIX_EPOCH};

use serde::{Deserialize, Serialize};

use crate::error::{ExitCode, VoltaError};
use crate::hook::Publish;
use crate::monitor::send_events;
use crate::session::ActivityKind;

// the Event data that is serialized to JSON and sent the plugin
#[derive(Deserialize, Serialize)]
pub struct Event {
    timestamp: u64,
    pub name: String,
    pub event: EventKind,
}

#[derive(Deserialize, Serialize, PartialEq, Eq, Debug)]
pub struct ErrorEnv {
    argv: String,
    exec_path: String,
    path: String,
    platform: String,
    platform_version: String,
}

#[derive(Deserialize, Serialize, PartialEq, Eq, Debug)]
#[serde(rename_all = "lowercase")]
pub enum EventKind {
    Start,
    End {
        exit_code: i32,
    },
    Error {
        exit_code: i32,
        error: String,
        env: ErrorEnv,
    },
    ToolEnd {
        exit_code: i32,
    },
    Args {
        argv: String,
    },
}

impl EventKind {
    pub fn into_event(self, activity_kind: ActivityKind) -> Event {
        Event {
            timestamp: unix_timestamp(),
            name: activity_kind.to_string(),
            event: self,
        }
    }
}

// returns the current number of milliseconds since the epoch
fn unix_timestamp() -> u64 {
    let start = SystemTime::now();
    let duration = start
        .duration_since(UNIX_EPOCH)
        .expect("Time went backwards");
    let nanosecs_since_epoch = duration.as_secs() * 1_000_000_000 + duration.subsec_nanos() as u64;
    nanosecs_since_epoch / 1_000_000
}

fn get_error_env() -> ErrorEnv {
    let path = match env::var("PATH") {
        Ok(p) => p,
        Err(_e) => "error: Unable to get path from environment".to_string(),
    };
    let argv = env::args().collect::<Vec<String>>().join(" ");
    let exec_path = match env::current_exe() {
        Ok(ep) => ep.display().to_string(),
        Err(_e) => "error: Unable to get executable path from environment".to_string(),
    };

    let info = os_info::get();
    let platform = info.os_type().to_string();
    let platform_version = info.version().to_string();

    ErrorEnv {
        argv,
        exec_path,
        path,
        platform,
        platform_version,
    }
}

pub struct EventLog {
    events: Vec<Event>,
}

impl EventLog {
    /// Constructs a new 'EventLog'
    pub fn init() -> Self {
        EventLog { events: Vec::new() }
    }

    pub fn add_event_start(&mut self, activity_kind: ActivityKind) {
        self.add_event(EventKind::Start, activity_kind)
    }
    pub fn add_event_end(&mut self, activity_kind: ActivityKind, exit_code: ExitCode) {
        self.add_event(
            EventKind::End {
                exit_code: exit_code as i32,
            },
            activity_kind,
        )
    }
    pub fn add_event_tool_end(&mut self, activity_kind: ActivityKind, exit_code: i32) {
        self.add_event(EventKind::ToolEnd { exit_code }, activity_kind)
    }
    pub fn add_event_error(&mut self, activity_kind: ActivityKind, error: &VoltaError) {
        self.add_event(
            EventKind::Error {
                exit_code: error.exit_code() as i32,
                error: error.to_string(),
                env: get_error_env(),
            },
            activity_kind,
        )
    }
    pub fn add_event_args(&mut self) {
        let argv = env::args_os()
            .enumerate()
            .fold(String::new(), |mut result, (i, arg)| {
                if i > 0 {
                    result.push(' ');
                }
                result.push_str(&arg.to_string_lossy());
                result
            });
        self.add_event(EventKind::Args { argv }, ActivityKind::Args)
    }

    fn add_event(&mut self, event_kind: EventKind, activity_kind: ActivityKind) {
        let event = event_kind.into_event(activity_kind);
        self.events.push(event);
    }

    pub fn publish(&self, plugin: Option<&Publish>) {
        match plugin {
            // Note: This call to unimplemented is left in, as it's not a Fallible operation that can use ErrorKind::Unimplemented
            Some(Publish::Url(_)) => unimplemented!(),
            Some(Publish::Bin(command)) => {
                send_events(command, &self.events);
            }
            None => {}
        }
    }
}

#[cfg(test)]
pub mod tests {

    use super::{EventKind, EventLog};
    use crate::error::{ErrorKind, ExitCode};
    use crate::session::ActivityKind;
    use regex::Regex;

    #[test]
    fn test_adding_events() {
        let mut event_log = EventLog::init();
        assert_eq!(event_log.events.len(), 0);

        event_log.add_event_start(ActivityKind::Current);
        assert_eq!(event_log.events.len(), 1);
        assert_eq!(event_log.events[0].name, "current");
        assert_eq!(event_log.events[0].event, EventKind::Start);

        event_log.add_event_end(ActivityKind::Pin, ExitCode::NetworkError);
        assert_eq!(event_log.events.len(), 2);
        assert_eq!(event_log.events[1].name, "pin");
        assert_eq!(event_log.events[1].event, EventKind::End { exit_code: 5 });

        event_log.add_event_tool_end(ActivityKind::Version, 12);
        assert_eq!(event_log.events.len(), 3);
        assert_eq!(event_log.events[2].name, "version");
        assert_eq!(
            event_log.events[2].event,
            EventKind::ToolEnd { exit_code: 12 }
        );

        let error = ErrorKind::BinaryExecError.into();
        event_log.add_event_error(ActivityKind::Install, &error);
        assert_eq!(event_log.events.len(), 4);
        assert_eq!(event_log.events[3].name, "install");
        // not checking the error because it has too much machine-specific info

        event_log.add_event_args();
        assert_eq!(event_log.events.len(), 5);
        assert_eq!(event_log.events[4].name, "args");
        match event_log.events[4].event {
            EventKind::Args { ref argv } => {
                let re = Regex::new("volta_core").unwrap();
                assert!(re.is_match(argv));
            }
            _ => {
                panic!(
                    "Expected EventKind::Args {{ argv }}, Got: {:?}",
                    event_log.events[4].event
                );
            }
        }
    }
}


================================================
FILE: crates/volta-core/src/fs.rs
================================================
//! Provides utilities for operating on the filesystem.

use std::fs::{self, create_dir_all, read_dir, DirEntry, File, Metadata};
use std::io;
#[cfg(unix)]
use std::os::unix::fs::PermissionsExt;
use std::path::Path;

use crate::error::{Context, ErrorKind, Fallible};
use crate::layout::volta_home;
use retry::delay::Fibonacci;
use retry::{retry, OperationResult};
use tempfile::{tempdir_in, NamedTempFile, TempDir};

/// Opens a file, creating it if it doesn't exist
pub fn touch(path: &Path) -> io::Result<File> {
    if !path.is_file() {
        if let Some(basedir) = path.parent() {
            create_dir_all(basedir)?;
        }
        File::create(path)?;
    }
    File::open(path)
}

/// Removes the target directory, if it exists. If the directory doesn't exist, that is treated as
/// success.
pub fn remove_dir_if_exists<P: AsRef<Path>>(path: P) -> Fallible<()> {
    fs::remove_dir_all(&path)
        .or_else(ok_if_not_found)
        .with_context(|| ErrorKind::DeleteDirectoryError {
            directory: path.as_ref().to_owned(),
        })
}

/// Removes the target file, if it exists. If the file doesn't exist, that is treated as success.
pub fn remove_file_if_exists<P: AsRef<Path>>(path: P) -> Fallible<()> {
    fs::remove_file(&path)
        .or_else(ok_if_not_found)
        .with_context(|| ErrorKind::DeleteFileError {
            file: path.as_ref().to_owned(),
        })
}

/// Converts a failure because of file not found into a success.
///
/// Handling the error is preferred over checking if a file exists before removing it, since
/// that avoids a potential race condition between the check and the removal.
pub fn ok_if_not_found<T: Default>(err: io::Error) -> io::Result<T> {
    match err.kind() {
        io::ErrorKind::NotFound => Ok(T::default()),
        _ => Err(err),
    }
}

/// Reads a file, if it exists.
pub fn read_file<P: AsRef<Path>>(path: P) -> io::Result<Option<String>> {
    let result: io::Result<String> = fs::read_to_string(path);

    match result {
        Ok(string) => Ok(Some(string)),
        Err(error) => match error.kind() {
            io::ErrorKind::NotFound => Ok(None),
            _ => Err(error),
        },
    }
}

/// Reads the full contents of a directory, eagerly extracting each directory entry
/// and its metadata and returning an iterator over them. Returns `Error` if any of
/// these steps fails.
///
/// This function makes it easier to write high level logic for manipulating the
/// contents of directories (map, filter, etc).
///
/// Note that this function allocates an intermediate vector of directory entries to
/// construct the iterator from, so if a directory is expected to be very large, it
/// will allocate temporary data proportional to the number of entries.
pub fn read_dir_eager(dir: &Path) -> io::Result<impl Iterator<Item = (DirEntry, Metadata)>> {
    let entries = read_dir(dir)?;
    let vec = entries
        .map(|entry| {
            let entry = entry?;
            let metadata = entry.metadata()?;
            Ok((entry, metadata))
        })
        .collect::<io::Result<Vec<(DirEntry, Metadata)>>>()?;

    Ok(vec.into_iter())
}

/// Reads the contents of a directory and returns a Vec of the matched results
/// from the input function
pub fn dir_entry_match<T, F>(dir: &Path, mut f: F) -> io::Result<Vec<T>>
where
    F: FnMut(&DirEntry) -> Option<T>,
{
    let entries = read_dir_eager(dir)?;
    Ok(entries
        .filter(|(_, metadata)| metadata.is_file())
        .filter_map(|(entry, _)| f(&entry))
        .collect::<Vec<T>>())
}

/// Creates a NamedTempFile in the Volta tmp directory
pub fn create_staging_file() -> Fallible<NamedTempFile> {
    let tmp_dir = volta_home()?.tmp_dir();
    NamedTempFile::new_in(tmp_dir).with_context(|| ErrorKind::CreateTempFileError {
        in_dir: tmp_dir.to_owned(),
    })
}

/// Creates a staging directory in the Volta tmp directory
pub fn create_staging_dir() -> Fallible<TempDir> {
    let tmp_root = volta_home()?.tmp_dir();
    tempdir_in(tmp_root).with_context(|| ErrorKind::CreateTempDirError {
        in_dir: tmp_root.to_owned(),
    })
}

/// Create a file symlink. The `dst` path will be a symbolic link pointing to the `src` path.
pub fn symlink_file<S, D>(src: S, dest: D) -> io::Result<()>
where
    S: AsRef<Path>,
    D: AsRef<Path>,
{
    #[cfg(windows)]
    return std::os::windows::fs::symlink_file(src, dest);

    #[cfg(unix)]
    return std::os::unix::fs::symlink(src, dest);
}

/// Create a directory symlink. The `dst` path will be a symbolic link pointing to the `src` path
pub fn symlink_dir<S, D>(src: S, dest: D) -> io::Result<()>
where
    S: AsRef<Path>,
    D: AsRef<Path>,
{
    #[cfg(windows)]
    return junction::create(src, dest);

    #[cfg(unix)]
    return std::os::unix::fs::symlink(src, dest);
}

/// Ensure that a given file has 'executable' permissions, otherwise we won't be able to call it
#[cfg(unix)]
pub fn set_executable(bin: &Path) -> io::Result<()> {
    let mut permissions = fs::metadata(bin)?.permissions();
    let mode = permissions.mode();

    if mode & 0o111 != 0o111 {
        permissions.set_mode(mode | 0o111);
        fs::set_permissions(bin, permissions)
    } else {
        Ok(())
    }
}

/// Ensure that a given file has 'executable' permissions, otherwise we won't be able to call it
///
/// Note: This is a no-op on Windows, which has no concept of 'executable' permissions
#[cfg(windows)]
pub fn set_executable(_bin: &Path) -> io::Result<()> {
    Ok(())
}

/// Rename a file or directory to a new name, retrying if the operation fails because of permissions
///
/// Will retry for ~30 seconds with longer and longer delays between each, to allow for virus scan
/// and other automated operations to complete.
pub fn rename<F, T>(from: F, to: T) -> io::Result<()>
where
    F: AsRef<Path>,
    T: AsRef<Path>,
{
    // 21 Fibonacci steps starting at 1 ms is ~28 seconds total
    // See https://github.com/rust-lang/rustup/pull/1873 where this was used by Rustup to work around
    // virus scanning file locks
    let from = from.as_ref();
    let to = to.as_ref();

    retry(Fibonacci::from_millis(1).take(21), || {
        match fs::rename(from, to) {
            Ok(_) => OperationResult::Ok(()),
            Err(e) => match e.kind() {
                io::ErrorKind::PermissionDenied => OperationResult::Retry(e),
                _ => OperationResult::Err(e),
            },
        }
    })
    .map_err(|e| e.error)
}


================================================
FILE: crates/volta-core/src/hook/mod.rs
================================================
//! Provides types for working with Volta hooks.

use std::borrow::Cow;
use std::fs::File;
use std::iter::once;
use std::marker::PhantomData;
use std::path::Path;

use crate::error::{Context, ErrorKind, Fallible};
use crate::layout::volta_home;
use crate::project::Project;
use crate::tool::{Node, Npm, Pnpm, Tool};
use log::debug;
use once_cell::unsync::OnceCell;

pub(crate) mod serial;
pub mod tool;

/// A hook for publishing Volta events.
#[derive(PartialEq, Eq, Debug)]
pub enum Publish {
    /// Reports an event by sending a POST request to a URL.
    Url(String),

    /// Reports an event by forking a process and sending the event by IPC.
    Bin(String),
}

/// Lazily loaded Volta hook configuration
pub struct LazyHookConfig {
    settings: OnceCell<HookConfig>,
}

impl LazyHookConfig {
    /// Constructs a new `LazyHookConfig`
    pub fn init() -> LazyHookConfig {
        LazyHookConfig {
            settings: OnceCell::new(),
        }
    }

    /// Forces the loading of the hook configuration from both project-local and user-default hooks
    pub fn get(&self, project: Option<&Project>) -> Fallible<&HookConfig> {
        self.settings
            .get_or_try_init(|| HookConfig::current(project))
    }
}

/// Volta hook configuration
pub struct HookConfig {
    node: Option<ToolHooks<Node>>,
    npm: Option<ToolHooks<Npm>>,
    pnpm: Option<ToolHooks<Pnpm>>,
    yarn: Option<YarnHooks>,
    events: Option<EventHooks>,
}

/// Volta hooks for an individual tool
pub struct ToolHooks<T: Tool> {
    /// The hook for resolving the URL for a distro version
    pub distro: Option<tool::DistroHook>,
    /// The hook for resolving the URL for the latest version
    pub latest: Option<tool::MetadataHook>,
    /// The hook for resolving the Tool Index URL
    pub index: Option<tool::MetadataHook>,

    phantom: PhantomData<T>,
}

/// Volta hooks for Yarn
pub struct YarnHooks {
    /// The hook for resolving the URL for a distro version
    pub distro: Option<tool::DistroHook>,
    /// The hook for resolving the URL for the latest version
    pub latest: Option<tool::MetadataHook>,
    /// The hook for resolving the Tool Index URL
    pub index: Option<tool::YarnIndexHook>,
}

impl<T: Tool> ToolHooks<T> {
    /// Extends this ToolHooks with another, giving precendence to the current instance
    fn merge(self, other: Self) -> Self {
        Self {
            distro: self.distro.or(other.distro),
            latest: self.latest.or(other.latest),
            index: self.index.or(other.index),
            phantom: PhantomData,
        }
    }
}

impl YarnHooks {
    /// Extends this YarnHooks with another, giving precendence to the current instance
    fn merge(self, other: Self) -> Self {
        Self {
            distro: self.distro.or(other.distro),
            latest: self.latest.or(other.latest),
            index: self.index.or(other.index),
        }
    }
}

macro_rules! merge_hooks {
    ($self:ident, $other:ident, $field:ident) => {
        match ($self.$field, $other.$field) {
            (Some(current), Some(other)) => Some(current.merge(other)),
            (Some(single), None) | (None, Some(single)) => Some(single),
            (None, None) => None,
        }
    };
}

impl HookConfig {
    pub fn node(&self) -> Option<&ToolHooks<Node>> {
        self.node.as_ref()
    }

    pub fn npm(&self) -> Option<&ToolHooks<Npm>> {
        self.npm.as_ref()
    }

    pub fn pnpm(&self) -> Option<&ToolHooks<Pnpm>> {
        self.pnpm.as_ref()
    }

    pub fn yarn(&self) -> Option<&YarnHooks> {
        self.yarn.as_ref()
    }

    pub fn events(&self) -> Option<&EventHooks> {
        self.events.as_ref()
    }

    /// Returns the current hooks, which are a merge between the user hooks and
    /// the project hooks (if any).
    fn current(project: Option<&Project>) -> Fallible<Self> {
        let default_hooks_file = volta_home()?.default_hooks_file();

        // Since `from_paths` expects the paths to be sorted in descending precedence order, we
        // include all project hooks first (workspace_roots is already sorted in descending
        // precedence order)
        // See the per-project configuration RFC for more details on the configuration precedence:
        // https://github.com/volta-cli/rfcs/blob/main/text/0033-per-project-config.md#configuration-precedence
        let paths = project
            .into_iter()
            .flat_map(Project::workspace_roots)
            .map(|root| {
                let mut path = root.join(".volta");
                path.push("hooks.json");
                Cow::Owned(path)
            })
            .chain(once(Cow::Borrowed(default_hooks_file)));

        Self::from_paths(paths)
    }

    /// Returns the merged hooks loaded from an iterator of potential hook files
    ///
    /// `paths` should be sorted in order of descending precedence.
    fn from_paths<P, I>(paths: I) -> Fallible<Self>
    where
        P: AsRef<Path>,
        I: IntoIterator<Item = P>,
    {
        paths
            .into_iter()
            .try_fold(None, |acc: Option<Self>, hooks_file| {
                // Try to load the hooks and merge with any already loaded hooks
                match Self::from_file(hooks_file.as_ref())? {
                    Some(hooks) => {
                        debug!(
                            "Loaded custom hooks file: {}",
                            hooks_file.as_ref().display()
                        );
                        Ok(Some(match acc {
                            Some(loaded) => loaded.merge(hooks),
                            None => hooks,
                        }))
                    }
                    None => Ok(acc),
                }
            })
            // If there were no hooks loaded at all, provide a default empty HookConfig
            .map(|maybe_config| {
                maybe_config.unwrap_or_else(|| {
                    debug!("No custom hooks found");
                    Self {
                        node: None,
                        npm: None,
                        pnpm: None,
                        yarn: None,
                        events: None,
                    }
                })
            })
    }

    fn from_file(file_path: &Path) -> Fallible<Option<Self>> {
        if !file_path.is_file() {
            return Ok(None);
        }

        let file = File::open(file_path).with_context(|| ErrorKind::ReadHooksError {
            file: file_path.to_path_buf(),
        })?;

        let raw: serial::RawHookConfig =
            serde_json::de::from_reader(file).with_context(|| ErrorKind::ParseHooksError {
                file: file_path.to_path_buf(),
            })?;

        // Invariant: Since we successfully loaded it, we know we have a valid file path
        let hooks_path = file_path.parent().expect("File paths always have a parent");

        raw.into_hook_config(hooks_path).map(Some)
    }

    /// Merges this HookConfig with another, giving precedence to the current instance
    fn merge(self, other: Self) -> Self {
        Self {
            node: merge_hooks!(self, other, node),
            npm: merge_hooks!(self, other, npm),
            pnpm: merge_hooks!(self, other, pnpm),
            yarn: merge_hooks!(self, other, yarn),
            events: merge_hooks!(self, other, events),
        }
    }
}

/// Format of the registry used for Yarn (Npm or Github)
#[derive(PartialEq, Eq, Debug)]
pub enum RegistryFormat {
    Npm,
    Github,
}

impl RegistryFormat {
    pub fn from_str(raw_format: &str) -> Fallible<RegistryFormat> {
        match raw_format {
            "npm" => Ok(RegistryFormat::Npm),
            "github" => Ok(RegistryFormat::Github),
            other => Err(ErrorKind::InvalidRegistryFormat {
                format: String::from(other),
            }
            .into()),
        }
    }
}

/// Volta hooks related to events.
pub struct EventHooks {
    /// The hook for publishing events, if any.
    pub publish: Option<Publish>,
}

impl EventHooks {
    /// Merges this EventHooks with another, giving precedence to the current instance
    fn merge(self, other: Self) -> Self {
        Self {
            publish: self.publish.or(other.publish),
        }
    }
}

#[cfg(test)]
pub mod tests {

    use super::{tool, HookConfig, Publish, RegistryFormat};
    use std::path::PathBuf;

    fn fixture_path(fixture_dir: &str) -> PathBuf {
        let mut cargo_manifest_dir = PathBuf::from(env!("CARGO_MANIFEST_DIR"));
        cargo_manifest_dir.push("fixtures");
        cargo_manifest_dir.push(fixture_dir);
        cargo_manifest_dir
    }

    #[test]
    fn test_from_str_event_url() {
        let fixture_dir = fixture_path("hooks");
        let url_file = fixture_dir.join("event_url.json");
        let hooks = HookConfig::from_file(&url_file).unwrap().unwrap();

        assert_eq!(
            hooks.events.unwrap().publish,
            Some(Publish::Url("https://google.com".to_string()))
        );
    }

    #[test]
    fn test_from_str_bins() {
        let fixture_dir = fixture_path("hooks");
        let bin_file = fixture_dir.join("bins.json");
        let hooks = HookConfig::from_file(&bin_file).unwrap().unwrap();
        let node = hooks.node.unwrap();
        let pnpm = hooks.pnpm.unwrap();
        let yarn = hooks.yarn.unwrap();

        assert_eq!(
            node.distro,
            Some(tool::DistroHook::Bin {
                bin: "/some/bin/for/node/distro".to_string(),
                base_path: fixture_dir.clone(),
            })
        );
        assert_eq!(
            node.latest,
            Some(tool::MetadataHook::Bin {
                bin: "/some/bin/for/node/latest".to_string(),
                base_path: fixture_dir.clone(),
            })
        );
        assert_eq!(
            node.index,
            Some(tool::MetadataHook::Bin {
                bin: "/some/bin/for/node/index".to_string(),
                base_path: fixture_dir.clone(),
            })
        );
        // pnpm
        assert_eq!(
            pnpm.distro,
            Some(tool::DistroHook::Bin {
                bin: "/bin/to/pnpm/distro".to_string(),
                base_path: fixture_dir.clone(),
            })
        );
        assert_eq!(
            pnpm.latest,
            Some(tool::MetadataHook::Bin {
                bin: "/bin/to/pnpm/latest".to_string(),
                base_path: fixture_dir.clone(),
            })
        );
        assert_eq!(
            pnpm.index,
            Some(tool::MetadataHook::Bin {
                bin: "/bin/to/pnpm/index".to_string(),
                base_path: fixture_dir.clone(),
            })
        );
        // Yarn
        assert_eq!(
            yarn.distro,
            Some(tool::DistroHook::Bin {
                bin: "/bin/to/yarn/distro".to_string(),
                base_path: fixture_dir.clone(),
            })
        );
        assert_eq!(
            yarn.latest,
            Some(tool::MetadataHook::Bin {
                bin: "/bin/to/yarn/latest".to_string(),
                base_path: fixture_dir.clone(),
            })
        );
        assert_eq!(
            yarn.index,
            Some(tool::YarnIndexHook {
                format: RegistryFormat::Github,
                metadata: tool::MetadataHook::Bin {
                    bin: "/bin/to/yarn/index".to_string(),
                    base_path: fixture_dir,
                },
            })
        );
        assert_eq!(
            hooks.events.unwrap().publish,
            Some(Publish::Bin("/events/bin".to_string()))
        );
    }

    #[test]
    fn test_from_str_prefixes() {
        let fixture_dir = fixture_path("hooks");
        let prefix_file = fixture_dir.join("prefixes.json");
        let hooks = HookConfig::from_file(&prefix_file).unwrap().unwrap();
        let node = hooks.node.unwrap();
        let pnpm = hooks.pnpm.unwrap();
        let yarn = hooks.yarn.unwrap();

        assert_eq!(
            node.distro,
            Some(tool::DistroHook::Prefix(
Download .txt
gitextract_9r0abwvz/

├── .cargo/
│   └── config.toml
├── .github/
│   ├── dependabot.yml
│   └── workflows/
│       ├── api-docs.yml
│       ├── release.yml
│       └── test.yml
├── .gitignore
├── .vscode/
│   ├── launch.json
│   └── settings.json
├── CODE_OF_CONDUCT.md
├── COMPATIBILITY.md
├── CONTRIBUTING.md
├── Cargo.toml
├── LICENSE
├── README.md
├── RELEASES.md
├── ci/
│   ├── build-linux.sh
│   ├── build-macos.sh
│   ├── docker/
│   │   └── Dockerfile
│   └── volta.manifest
├── crates/
│   ├── archive/
│   │   ├── Cargo.toml
│   │   └── src/
│   │       ├── lib.rs
│   │       ├── tarball.rs
│   │       └── zip.rs
│   ├── fs-utils/
│   │   ├── Cargo.toml
│   │   └── src/
│   │       └── lib.rs
│   ├── progress-read/
│   │   ├── Cargo.toml
│   │   └── src/
│   │       └── lib.rs
│   ├── test-support/
│   │   ├── Cargo.toml
│   │   └── src/
│   │       ├── lib.rs
│   │       ├── matchers.rs
│   │       ├── paths.rs
│   │       └── process.rs
│   ├── validate-npm-package-name/
│   │   ├── Cargo.toml
│   │   └── src/
│   │       └── lib.rs
│   ├── volta-core/
│   │   ├── Cargo.toml
│   │   ├── fixtures/
│   │   │   ├── basic/
│   │   │   │   ├── package.json
│   │   │   │   └── subdir/
│   │   │   │       └── .gitkeep
│   │   │   ├── cycle-1/
│   │   │   │   ├── package.json
│   │   │   │   └── volta.json
│   │   │   ├── cycle-2/
│   │   │   │   ├── package.json
│   │   │   │   ├── workspace-1.json
│   │   │   │   └── workspace-2.json
│   │   │   ├── hooks/
│   │   │   │   ├── bins.json
│   │   │   │   ├── event_url.json
│   │   │   │   ├── format_github.json
│   │   │   │   ├── format_npm.json
│   │   │   │   ├── prefixes.json
│   │   │   │   ├── project/
│   │   │   │   │   ├── .volta/
│   │   │   │   │   │   └── hooks.json
│   │   │   │   │   └── package.json
│   │   │   │   └── templates.json
│   │   │   ├── nested/
│   │   │   │   ├── package.json
│   │   │   │   └── subproject/
│   │   │   │       ├── inner_project/
│   │   │   │       │   └── package.json
│   │   │   │       └── package.json
│   │   │   ├── no_toolchain/
│   │   │   │   └── package.json
│   │   │   └── yarn/
│   │   │       ├── pnp-cjs/
│   │   │       │   ├── .pnp.cjs
│   │   │       │   └── package.json
│   │   │       ├── pnp-js/
│   │   │       │   ├── .pnp.js
│   │   │       │   └── package.json
│   │   │       └── yarnrc-yml/
│   │   │           ├── .yarnrc.yml
│   │   │           └── package.json
│   │   └── src/
│   │       ├── command.rs
│   │       ├── error/
│   │       │   ├── kind.rs
│   │       │   ├── mod.rs
│   │       │   └── reporter.rs
│   │       ├── event.rs
│   │       ├── fs.rs
│   │       ├── hook/
│   │       │   ├── mod.rs
│   │       │   ├── serial.rs
│   │       │   └── tool.rs
│   │       ├── inventory.rs
│   │       ├── layout/
│   │       │   ├── mod.rs
│   │       │   ├── unix.rs
│   │       │   └── windows.rs
│   │       ├── lib.rs
│   │       ├── log.rs
│   │       ├── monitor.rs
│   │       ├── platform/
│   │       │   ├── image.rs
│   │       │   ├── mod.rs
│   │       │   ├── system.rs
│   │       │   └── tests.rs
│   │       ├── project/
│   │       │   ├── mod.rs
│   │       │   ├── serial.rs
│   │       │   └── tests.rs
│   │       ├── run/
│   │       │   ├── binary.rs
│   │       │   ├── executor.rs
│   │       │   ├── mod.rs
│   │       │   ├── node.rs
│   │       │   ├── npm.rs
│   │       │   ├── npx.rs
│   │       │   ├── parser.rs
│   │       │   ├── pnpm.rs
│   │       │   └── yarn.rs
│   │       ├── session.rs
│   │       ├── shim.rs
│   │       ├── signal.rs
│   │       ├── style.rs
│   │       ├── sync.rs
│   │       ├── tool/
│   │       │   ├── mod.rs
│   │       │   ├── node/
│   │       │   │   ├── fetch.rs
│   │       │   │   ├── metadata.rs
│   │       │   │   ├── mod.rs
│   │       │   │   └── resolve.rs
│   │       │   ├── npm/
│   │       │   │   ├── fetch.rs
│   │       │   │   ├── mod.rs
│   │       │   │   └── resolve.rs
│   │       │   ├── package/
│   │       │   │   ├── configure.rs
│   │       │   │   ├── install.rs
│   │       │   │   ├── manager.rs
│   │       │   │   ├── metadata.rs
│   │       │   │   ├── mod.rs
│   │       │   │   └── uninstall.rs
│   │       │   ├── pnpm/
│   │       │   │   ├── fetch.rs
│   │       │   │   ├── mod.rs
│   │       │   │   └── resolve.rs
│   │       │   ├── registry.rs
│   │       │   ├── serial.rs
│   │       │   └── yarn/
│   │       │       ├── fetch.rs
│   │       │       ├── metadata.rs
│   │       │       ├── mod.rs
│   │       │       └── resolve.rs
│   │       ├── toolchain/
│   │       │   ├── mod.rs
│   │       │   └── serial.rs
│   │       └── version/
│   │           ├── mod.rs
│   │           └── serial.rs
│   ├── volta-layout/
│   │   ├── Cargo.toml
│   │   └── src/
│   │       ├── lib.rs
│   │       ├── macros.rs
│   │       ├── v0.rs
│   │       ├── v1.rs
│   │       ├── v2.rs
│   │       ├── v3.rs
│   │       └── v4.rs
│   ├── volta-layout-macro/
│   │   ├── Cargo.toml
│   │   └── src/
│   │       ├── ast.rs
│   │       ├── ir.rs
│   │       └── lib.rs
│   └── volta-migrate/
│       ├── Cargo.toml
│       └── src/
│           ├── empty.rs
│           ├── lib.rs
│           ├── v0.rs
│           ├── v1.rs
│           ├── v2.rs
│           ├── v3/
│           │   └── config.rs
│           ├── v3.rs
│           └── v4.rs
├── dev/
│   ├── package.json
│   ├── rpm/
│   │   ├── build-rpm.sh
│   │   └── volta.spec
│   └── unix/
│       ├── SHASUMS256.txt
│       ├── boot-install.sh
│       ├── build.sh
│       ├── install.sh.in
│       ├── release.sh
│       ├── test-events
│       ├── tests/
│       │   └── install-script.bats
│       ├── volta-install-legacy.sh
│       └── volta-install.sh
├── rust-toolchain.toml
├── src/
│   ├── cli.rs
│   ├── command/
│   │   ├── completions.rs
│   │   ├── fetch.rs
│   │   ├── install.rs
│   │   ├── list/
│   │   │   ├── human.rs
│   │   │   ├── mod.rs
│   │   │   ├── plain.rs
│   │   │   └── toolchain.rs
│   │   ├── mod.rs
│   │   ├── pin.rs
│   │   ├── run.rs
│   │   ├── setup.rs
│   │   ├── uninstall.rs
│   │   ├── use.rs
│   │   └── which.rs
│   ├── common.rs
│   ├── main.rs
│   ├── volta-migrate.rs
│   └── volta-shim.rs
├── tests/
│   ├── acceptance/
│   │   ├── corrupted_download.rs
│   │   ├── direct_install.rs
│   │   ├── direct_uninstall.rs
│   │   ├── execute_binary.rs
│   │   ├── hooks.rs
│   │   ├── main.rs
│   │   ├── merged_platform.rs
│   │   ├── migrations.rs
│   │   ├── run_shim_directly.rs
│   │   ├── support/
│   │   │   ├── events_helpers.rs
│   │   │   ├── mod.rs
│   │   │   └── sandbox.rs
│   │   ├── verbose_errors.rs
│   │   ├── volta_bypass.rs
│   │   ├── volta_install.rs
│   │   ├── volta_pin.rs
│   │   ├── volta_run.rs
│   │   └── volta_uninstall.rs
│   ├── fixtures/
│   │   ├── cli-dist-2.4.159.tgz
│   │   ├── cli-dist-3.12.99.tgz
│   │   ├── cli-dist-3.2.42.tgz
│   │   ├── cli-dist-3.7.71.tgz
│   │   ├── npm-1.2.3.tgz
│   │   ├── npm-4.5.6.tgz
│   │   ├── npm-8.1.5.tgz
│   │   ├── pnpm-0.0.1.tgz
│   │   ├── pnpm-6.34.0.tgz
│   │   ├── pnpm-7.7.1.tgz
│   │   ├── volta-test-1.0.0.tgz
│   │   ├── yarn-0.0.1.tgz
│   │   ├── yarn-1.12.99.tgz
│   │   ├── yarn-1.2.42.tgz
│   │   ├── yarn-1.4.159.tgz
│   │   └── yarn-1.7.71.tgz
│   └── smoke/
│       ├── autodownload.rs
│       ├── direct_install.rs
│       ├── direct_upgrade.rs
│       ├── main.rs
│       ├── npm_link.rs
│       ├── package_migration.rs
│       ├── support/
│       │   ├── mod.rs
│       │   └── temp_project.rs
│       ├── volta_fetch.rs
│       ├── volta_install.rs
│       └── volta_run.rs
├── volta.iml
└── wix/
    ├── License.rtf
    ├── main.wxs
    └── shim.cmd
Download .txt
SYMBOL INDEX (1680 symbols across 133 files)

FILE: crates/archive/src/lib.rs
  type ArchiveError (line 18) | pub enum ArchiveError {
  type Origin (line 40) | pub enum Origin {
  type Archive (line 45) | pub trait Archive {
    method compressed_size (line 46) | fn compressed_size(&self) -> u64;
    method unpack (line 49) | fn unpack(
    method origin (line 55) | fn origin(&self) -> Origin;
  function content_length (line 100) | fn content_length(headers: &HeaderMap) -> Result<u64, ArchiveError> {

FILE: crates/archive/src/tarball.rs
  type Tarball (line 15) | pub struct Tarball {
    method load (line 23) | pub fn load(source: File) -> Result<Box<dyn Archive>, ArchiveError> {
    method fetch (line 35) | pub fn fetch(url: &str, cache_file: &Path) -> Result<Box<dyn Archive>,...
  method compressed_size (line 57) | fn compressed_size(&self) -> u64 {
  method unpack (line 60) | fn unpack(
  method origin (line 70) | fn origin(&self) -> Origin {
  function fixture_path (line 82) | fn fixture_path(fixture_dir: &str) -> PathBuf {
  function test_load (line 90) | fn test_load() {

FILE: crates/archive/src/zip.rs
  type Zip (line 18) | pub struct Zip {
    method load (line 26) | pub fn load(source: File) -> Result<Box<dyn Archive>, ArchiveError> {
    method fetch (line 38) | pub fn fetch(url: &str, cache_file: &Path) -> Result<Box<dyn Archive>,...
  method compressed_size (line 60) | fn compressed_size(&self) -> u64 {
  method unpack (line 63) | fn unpack(
  method origin (line 74) | fn origin(&self) -> Origin {
  function fixture_path (line 86) | fn fixture_path(fixture_dir: &str) -> PathBuf {
  function test_load (line 94) | fn test_load() {

FILE: crates/fs-utils/src/lib.rs
  function ensure_containing_dir_exists (line 8) | pub fn ensure_containing_dir_exists<P: AsRef<Path>>(path: &P) -> io::Res...

FILE: crates/progress-read/src/lib.rs
  type ProgressRead (line 7) | pub struct ProgressRead<R: Read, T, F: FnMut(&T, usize) -> T> {
  method read (line 20) | fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
  function new (line 34) | pub fn new(source: R, init: T, progress: F) -> ProgressRead<R, T, F> {
  method seek (line 44) | fn seek(&mut self, pos: SeekFrom) -> io::Result<u64> {

FILE: crates/test-support/src/matchers.rs
  type Execs (line 11) | pub struct Execs {
    method with_stdout (line 29) | pub fn with_stdout<S: ToString>(mut self, expected: S) -> Execs {
    method with_stderr (line 36) | pub fn with_stderr<S: ToString>(mut self, expected: S) -> Execs {
    method _with_stderr (line 41) | fn _with_stderr(&mut self, expected: &dyn ToString) {
    method with_status (line 46) | pub fn with_status(mut self, expected: i32) -> Execs {
    method with_stdout_contains (line 54) | pub fn with_stdout_contains<S: ToString>(mut self, expected: S) -> Exe...
    method with_stderr_contains (line 62) | pub fn with_stderr_contains<S: ToString>(mut self, expected: S) -> Exe...
    method with_either_contains (line 70) | pub fn with_either_contains<S: ToString>(mut self, expected: S) -> Exe...
    method with_stdout_contains_n (line 78) | pub fn with_stdout_contains_n<S: ToString>(mut self, expected: S, numb...
    method with_stdout_does_not_contain (line 87) | pub fn with_stdout_does_not_contain<S: ToString>(mut self, expected: S...
    method with_stderr_does_not_contain (line 100) | pub fn with_stderr_does_not_contain<S: ToString>(mut self, expected: S...
    method with_stderr_unordered (line 120) | pub fn with_stderr_unordered<S: ToString>(mut self, expected: S) -> Ex...
    method with_json (line 140) | pub fn with_json(mut self, expected: &str) -> Execs {
    method match_output (line 150) | fn match_output(&self, actual: &Output) -> MatchResult {
    method match_status (line 156) | fn match_status(&self, actual: &Output) -> MatchResult {
    method match_stdout (line 169) | fn match_stdout(&self, actual: &Output) -> MatchResult {
    method match_stderr (line 297) | fn match_stderr(&self, actual: &Output) -> MatchResult {
    method match_std (line 307) | fn match_std(
    method match_json (line 454) | fn match_json(&self, expected: &Value, line: &str) -> MatchResult {
    method diff_lines (line 472) | fn diff_lines<'a>(
    method fmt (line 630) | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
    method fmt (line 636) | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
    method matches (line 642) | fn matches(&self, mut process: ProcessBuilder) -> MatchResult {
    method matches (line 648) | fn matches(&self, process: &'a mut ProcessBuilder) -> MatchResult {
    method matches (line 665) | fn matches(&self, output: Output) -> MatchResult {
  type MatchKind (line 502) | enum MatchKind {
  function lines_match (line 518) | pub fn lines_match(expected: &str, actual: &str) -> bool {
  function lines_match_works (line 538) | fn lines_match_works() {
  function find_mismatch (line 555) | fn find_mismatch<'a>(expected: &'a Value, actual: &'a Value) -> Option<(...
  type ZipAll (line 604) | struct ZipAll<I1: Iterator, I2: Iterator> {
  type Item (line 610) | type Item = (Option<T>, Option<T>);
  method next (line 611) | fn next(&mut self) -> Option<(Option<T>, Option<T>)> {
  function zip_all (line 622) | fn zip_all<T, I1: Iterator<Item = T>, I2: Iterator<Item = T>>(a: I1, b: ...
  function execs (line 670) | pub fn execs() -> Execs {
  function substitute_macros (line 687) | fn substitute_macros(input: &str) -> String {

FILE: crates/test-support/src/paths.rs
  function init (line 15) | fn init() {
  function global_root (line 32) | fn global_root() -> PathBuf {
  function root (line 49) | pub fn root() -> PathBuf {
  function home (line 54) | pub fn home() -> PathBuf {
  type Remove (line 58) | enum Remove {
    method to_str (line 63) | fn to_str(&self) -> &'static str {
    method at (line 70) | fn at(&self, path: &Path) {
  type PathExt (line 88) | pub trait PathExt {
    method rm (line 89) | fn rm(&self);
    method rm_rf (line 90) | fn rm_rf(&self);
    method rm_contents (line 91) | fn rm_contents(&self);
    method ensure_empty (line 92) | fn ensure_empty(&self);
    method mkdir_p (line 93) | fn mkdir_p(&self);
    method rm (line 98) | fn rm(&self) {
    method rm_rf (line 111) | fn rm_rf(&self) {
    method rm_contents (line 120) | fn rm_contents(&self) {
    method ensure_empty (line 132) | fn ensure_empty(&self) {
    method mkdir_p (line 138) | fn mkdir_p(&self) {

FILE: crates/test-support/src/process.rs
  type ProcessBuilder (line 13) | pub struct ProcessBuilder {
    method fmt (line 25) | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
    method program (line 38) | pub fn program<T: AsRef<OsStr>>(&mut self, program: T) -> &mut Process...
    method arg (line 44) | pub fn arg<T: AsRef<OsStr>>(&mut self, arg: T) -> &mut ProcessBuilder {
    method args (line 50) | pub fn args<T: AsRef<OsStr>>(&mut self, arguments: &[T]) -> &mut Proce...
    method args_replace (line 57) | pub fn args_replace<T: AsRef<OsStr>>(&mut self, arguments: &[T]) -> &m...
    method cwd (line 66) | pub fn cwd<T: AsRef<OsStr>>(&mut self, path: T) -> &mut ProcessBuilder {
    method env (line 72) | pub fn env<T: AsRef<OsStr>>(&mut self, key: &str, val: T) -> &mut Proc...
    method env_remove (line 79) | pub fn env_remove(&mut self, key: &str) -> &mut ProcessBuilder {
    method get_program (line 85) | pub fn get_program(&self) -> &OsString {
    method get_args (line 90) | pub fn get_args(&self) -> &[OsString] {
    method get_cwd (line 95) | pub fn get_cwd(&self) -> Option<&Path> {
    method get_env (line 101) | pub fn get_env(&self, var: &str) -> Option<OsString> {
    method get_envs (line 111) | pub fn get_envs(&self) -> &HashMap<String, Option<OsString>> {
    method exec (line 116) | pub fn exec(&self) -> Result<(), ProcessError> {
    method exec_with_output (line 142) | pub fn exec_with_output(&self) -> Result<Output, ProcessError> {
    method build_command (line 168) | pub fn build_command(&self) -> Command {
  function process (line 191) | pub fn process<T: AsRef<OsStr>>(cmd: T) -> ProcessBuilder {
  type ProcessError (line 202) | pub struct ProcessError {
  function process_error (line 208) | pub fn process_error(

FILE: crates/validate-npm-package-name/src/lib.rs
  constant BLACKLIST (line 24) | const BLACKLIST: [&str; 2] = ["node_modules", "favicon.ico"];
  constant BUILTINS (line 27) | const BUILTINS: [&str; 39] = [
  type Validity (line 71) | pub enum Validity {
    method valid_for_old_packages (line 86) | pub fn valid_for_old_packages(&self) -> bool {
    method valid_for_new_packages (line 90) | pub fn valid_for_new_packages(&self) -> bool {
  function validate (line 95) | pub fn validate(name: &str) -> Validity {
  function done (line 176) | fn done(warnings: Vec<String>, errors: Vec<String>) -> Validity {
  function traditional (line 189) | fn traditional() {
  function scoped (line 206) | fn scoped() {
  function invalid (line 219) | fn invalid() {
  function node_io_core (line 300) | fn node_io_core() {
  function long_package_names (line 310) | fn long_package_names() {
  function legacy_mixed_case (line 325) | fn legacy_mixed_case() {

FILE: crates/volta-core/src/error/kind.rs
  constant REPORT_BUG_CTA (line 10) | const REPORT_BUG_CTA: &str =
  constant PERMISSIONS_CTA (line 15) | const PERMISSIONS_CTA: &str = "Please ensure you have correct permission...
  type ErrorKind (line 19) | pub enum ErrorKind {
    method fmt (line 536) | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
    method exit_code (line 1460) | pub fn exit_code(&self) -> ExitCode {

FILE: crates/volta-core/src/error/mod.rs
  type Fallible (line 11) | pub type Fallible<T> = Result<T, VoltaError>;
  type VoltaError (line 15) | pub struct VoltaError {
    method exit_code (line 27) | pub fn exit_code(&self) -> ExitCode {
    method from_source (line 32) | pub fn from_source<E>(source: E, kind: ErrorKind) -> Self
    method kind (line 45) | pub fn kind(&self) -> &ErrorKind {
    method fmt (line 51) | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
    method from (line 63) | fn from(kind: ErrorKind) -> Self {
  type Inner (line 20) | struct Inner {
  method source (line 57) | fn source(&self) -> Option<&(dyn Error + 'static)> {
  type Context (line 71) | pub trait Context<T> {
    method with_context (line 72) | fn with_context<F>(self, f: F) -> Fallible<T>
  function with_context (line 81) | fn with_context<F>(self, f: F) -> Fallible<T>
  type ExitCode (line 91) | pub enum ExitCode {
    method exit (line 127) | pub fn exit(self) -> ! {

FILE: crates/volta-core/src/error/reporter.rs
  function report_error (line 17) | pub fn report_error(volta_version: &str, err: &VoltaError) {
  function write_error_log (line 47) | fn write_error_log(
  function compose_error_details (line 70) | fn compose_error_details(err: &VoltaError) -> Option<String> {
  function collect_arguments (line 94) | fn collect_arguments() -> String {

FILE: crates/volta-core/src/event.rs
  type Event (line 15) | pub struct Event {
  type ErrorEnv (line 22) | pub struct ErrorEnv {
  type EventKind (line 32) | pub enum EventKind {
    method into_event (line 51) | pub fn into_event(self, activity_kind: ActivityKind) -> Event {
  function unix_timestamp (line 61) | fn unix_timestamp() -> u64 {
  function get_error_env (line 70) | fn get_error_env() -> ErrorEnv {
  type EventLog (line 94) | pub struct EventLog {
    method init (line 100) | pub fn init() -> Self {
    method add_event_start (line 104) | pub fn add_event_start(&mut self, activity_kind: ActivityKind) {
    method add_event_end (line 107) | pub fn add_event_end(&mut self, activity_kind: ActivityKind, exit_code...
    method add_event_tool_end (line 115) | pub fn add_event_tool_end(&mut self, activity_kind: ActivityKind, exit...
    method add_event_error (line 118) | pub fn add_event_error(&mut self, activity_kind: ActivityKind, error: ...
    method add_event_args (line 128) | pub fn add_event_args(&mut self) {
    method add_event (line 141) | fn add_event(&mut self, event_kind: EventKind, activity_kind: Activity...
    method publish (line 146) | pub fn publish(&self, plugin: Option<&Publish>) {
  function test_adding_events (line 167) | fn test_adding_events() {

FILE: crates/volta-core/src/fs.rs
  function touch (line 16) | pub fn touch(path: &Path) -> io::Result<File> {
  function remove_dir_if_exists (line 28) | pub fn remove_dir_if_exists<P: AsRef<Path>>(path: P) -> Fallible<()> {
  function remove_file_if_exists (line 37) | pub fn remove_file_if_exists<P: AsRef<Path>>(path: P) -> Fallible<()> {
  function ok_if_not_found (line 49) | pub fn ok_if_not_found<T: Default>(err: io::Error) -> io::Result<T> {
  function read_file (line 57) | pub fn read_file<P: AsRef<Path>>(path: P) -> io::Result<Option<String>> {
  function read_dir_eager (line 79) | pub fn read_dir_eager(dir: &Path) -> io::Result<impl Iterator<Item = (Di...
  function dir_entry_match (line 94) | pub fn dir_entry_match<T, F>(dir: &Path, mut f: F) -> io::Result<Vec<T>>
  function create_staging_file (line 106) | pub fn create_staging_file() -> Fallible<NamedTempFile> {
  function create_staging_dir (line 114) | pub fn create_staging_dir() -> Fallible<TempDir> {
  function symlink_file (line 122) | pub fn symlink_file<S, D>(src: S, dest: D) -> io::Result<()>
  function symlink_dir (line 135) | pub fn symlink_dir<S, D>(src: S, dest: D) -> io::Result<()>
  function set_executable (line 149) | pub fn set_executable(bin: &Path) -> io::Result<()> {
  function set_executable (line 165) | pub fn set_executable(_bin: &Path) -> io::Result<()> {
  function rename (line 173) | pub fn rename<F, T>(from: F, to: T) -> io::Result<()>

FILE: crates/volta-core/src/hook/mod.rs
  type Publish (line 21) | pub enum Publish {
  type LazyHookConfig (line 30) | pub struct LazyHookConfig {
    method init (line 36) | pub fn init() -> LazyHookConfig {
    method get (line 43) | pub fn get(&self, project: Option<&Project>) -> Fallible<&HookConfig> {
  type HookConfig (line 50) | pub struct HookConfig {
    method node (line 114) | pub fn node(&self) -> Option<&ToolHooks<Node>> {
    method npm (line 118) | pub fn npm(&self) -> Option<&ToolHooks<Npm>> {
    method pnpm (line 122) | pub fn pnpm(&self) -> Option<&ToolHooks<Pnpm>> {
    method yarn (line 126) | pub fn yarn(&self) -> Option<&YarnHooks> {
    method events (line 130) | pub fn events(&self) -> Option<&EventHooks> {
    method current (line 136) | fn current(project: Option<&Project>) -> Fallible<Self> {
    method from_paths (line 160) | fn from_paths<P, I>(paths: I) -> Fallible<Self>
    method from_file (line 198) | fn from_file(file_path: &Path) -> Fallible<Option<Self>> {
    method merge (line 219) | fn merge(self, other: Self) -> Self {
  type ToolHooks (line 59) | pub struct ToolHooks<T: Tool> {
  type YarnHooks (line 71) | pub struct YarnHooks {
    method merge (line 94) | fn merge(self, other: Self) -> Self {
  function merge (line 82) | fn merge(self, other: Self) -> Self {
  type RegistryFormat (line 232) | pub enum RegistryFormat {
    method from_str (line 238) | pub fn from_str(raw_format: &str) -> Fallible<RegistryFormat> {
  type EventHooks (line 251) | pub struct EventHooks {
    method merge (line 258) | fn merge(self, other: Self) -> Self {
  function fixture_path (line 271) | fn fixture_path(fixture_dir: &str) -> PathBuf {
  function test_from_str_event_url (line 279) | fn test_from_str_event_url() {
  function test_from_str_bins (line 291) | fn test_from_str_bins() {
  function test_from_str_prefixes (line 374) | fn test_from_str_prefixes() {
  function test_from_str_templates (line 442) | fn test_from_str_templates() {
  function test_from_str_format_npm (line 511) | fn test_from_str_format_npm() {
  function test_from_str_format_github (line 549) | fn test_from_str_format_github() {
  function test_merge (line 587) | fn test_merge() {
  function test_from_paths (line 671) | fn test_from_paths() {

FILE: crates/volta-core/src/hook/serial.rs
  type RawResolveHook (line 11) | pub struct RawResolveHook {
    method into_hook (line 32) | fn into_hook<H, P, T, B>(self, to_prefix: P, to_template: T, to_bin: B...
    method into_distro_hook (line 63) | pub fn into_distro_hook(self, base_dir: &Path) -> Fallible<tool::Distr...
    method into_metadata_hook (line 74) | pub fn into_metadata_hook(self, base_dir: &Path) -> Fallible<tool::Met...
  type RawIndexHook (line 18) | pub struct RawIndexHook {
    method into_index_hook (line 87) | pub fn into_index_hook(self, base_dir: &Path) -> Fallible<tool::YarnIn...
  type RawPublishHook (line 26) | pub struct RawPublishHook {
  type Error (line 106) | type Error = VoltaError;
  function try_from (line 108) | fn try_from(raw: RawPublishHook) -> Fallible<super::Publish> {
  type RawHookConfig (line 128) | pub struct RawHookConfig {
    method into_hook_config (line 172) | pub fn into_hook_config(self, base_dir: &Path) -> Fallible<super::Hook...
  type RawEventHooks (line 138) | pub struct RawEventHooks {
  type Error (line 143) | type Error = VoltaError;
  function try_from (line 145) | fn try_from(raw: RawEventHooks) -> Fallible<super::EventHooks> {
  type RawToolHooks (line 154) | pub struct RawToolHooks<T: Tool> {
  type RawYarnHooks (line 165) | pub struct RawYarnHooks {
    method into_yarn_hooks (line 213) | pub fn into_yarn_hooks(self, base_dir: &Path) -> Fallible<super::YarnH...
  function into_tool_hooks (line 189) | pub fn into_tool_hooks(self, base_dir: &Path) -> Fallible<super::ToolHoo...

FILE: crates/volta-core/src/hook/tool.rs
  constant ARCH_TEMPLATE (line 17) | const ARCH_TEMPLATE: &str = "{{arch}}";
  constant OS_TEMPLATE (line 18) | const OS_TEMPLATE: &str = "{{os}}";
  constant VERSION_TEMPLATE (line 19) | const VERSION_TEMPLATE: &str = "{{version}}";
  constant EXTENSION_TEMPLATE (line 20) | const EXTENSION_TEMPLATE: &str = "{{ext}}";
  constant FILENAME_TEMPLATE (line 21) | const FILENAME_TEMPLATE: &str = "{{filename}}";
  type DistroHook (line 28) | pub enum DistroHook {
    method resolve (line 36) | pub fn resolve(&self, version: &Version, filename: &str) -> Fallible<S...
  function calculate_extension (line 58) | fn calculate_extension(filename: &str) -> Option<&str> {
  type MetadataHook (line 81) | pub enum MetadataHook {
    method resolve (line 89) | pub fn resolve(&self, filename: &str) -> Fallible<String> {
  type YarnIndexHook (line 103) | pub struct YarnIndexHook {
    method resolve (line 110) | pub fn resolve(&self, filename: &str) -> Fallible<String> {
  function execute_binary (line 123) | fn execute_binary(bin: &str, base_path: &Path, extra_arg: Option<String>...
  function test_distro_prefix_resolve (line 186) | fn test_distro_prefix_resolve() {
  function test_distro_template_resolve (line 200) | fn test_distro_template_resolve() {
  function test_metadata_prefix_resolve (line 230) | fn test_metadata_prefix_resolve() {
  function test_metadata_template_resolve (line 242) | fn test_metadata_template_resolve() {
  function test_calculate_extension (line 258) | fn test_calculate_extension() {

FILE: crates/volta-core/src/inventory.rs
  function node_available (line 18) | pub fn node_available(version: &Version) -> Fallible<bool> {
  function node_versions (line 27) | pub fn node_versions() -> Fallible<BTreeSet<Version>> {
  function npm_available (line 32) | pub fn npm_available(version: &Version) -> Fallible<bool> {
  function npm_versions (line 37) | pub fn npm_versions() -> Fallible<BTreeSet<Version>> {
  function pnpm_available (line 42) | pub fn pnpm_available(version: &Version) -> Fallible<bool> {
  function pnpm_versions (line 47) | pub fn pnpm_versions() -> Fallible<BTreeSet<Version>> {
  function yarn_available (line 52) | pub fn yarn_available(version: &Version) -> Fallible<bool> {
  function yarn_versions (line 57) | pub fn yarn_versions() -> Fallible<BTreeSet<Version>> {
  function package_configs (line 62) | pub fn package_configs() -> Fallible<BTreeSet<PackageConfig>> {
  function read_versions (line 96) | fn read_versions(dir: &Path) -> Fallible<BTreeSet<Version>> {

FILE: crates/volta-core/src/layout/mod.rs
  function volta_home (line 23) | pub fn volta_home<'a>() -> Fallible<&'a VoltaHome> {
  function volta_install (line 34) | pub fn volta_install<'a>() -> Fallible<&'a VoltaInstall> {
  function default_install_dir (line 51) | fn default_install_dir() -> Fallible<PathBuf> {

FILE: crates/volta-core/src/layout/unix.rs
  function default_home_dir (line 6) | pub(super) fn default_home_dir() -> Fallible<PathBuf> {
  function env_paths (line 12) | pub fn env_paths() -> Fallible<Vec<PathBuf>> {

FILE: crates/volta-core/src/layout/windows.rs
  function default_home_dir (line 6) | pub(super) fn default_home_dir() -> Fallible<PathBuf> {
  function env_paths (line 12) | pub fn env_paths() -> Fallible<Vec<PathBuf>> {

FILE: crates/volta-core/src/lib.rs
  constant VOLTA_FEATURE_PNPM (line 24) | const VOLTA_FEATURE_PNPM: &str = "VOLTA_FEATURE_PNPM";

FILE: crates/volta-core/src/log.rs
  constant ERROR_PREFIX (line 11) | const ERROR_PREFIX: &str = "error:";
  constant WARNING_PREFIX (line 12) | const WARNING_PREFIX: &str = "warning:";
  constant SHIM_ERROR_PREFIX (line 13) | const SHIM_ERROR_PREFIX: &str = "Volta error:";
  constant SHIM_WARNING_PREFIX (line 14) | const SHIM_WARNING_PREFIX: &str = "Volta warning:";
  constant MIGRATION_ERROR_PREFIX (line 15) | const MIGRATION_ERROR_PREFIX: &str = "Volta update error:";
  constant MIGRATION_WARNING_PREFIX (line 16) | const MIGRATION_WARNING_PREFIX: &str = "Volta update warning:";
  constant VOLTA_LOGLEVEL (line 17) | const VOLTA_LOGLEVEL: &str = "VOLTA_LOGLEVEL";
  constant ALLOWED_PREFIXES (line 18) | const ALLOWED_PREFIXES: [&str; 5] = [
  constant WRAP_INDENT (line 25) | const WRAP_INDENT: &str = "    ";
  type LogContext (line 28) | pub enum LogContext {
  type LogVerbosity (line 41) | pub enum LogVerbosity {
  type Logger (line 48) | pub struct Logger {
    method init (line 85) | pub fn init(context: LogContext, verbosity: LogVerbosity) -> Result<()...
    method new (line 92) | fn new(context: LogContext, verbosity: LogVerbosity) -> Self {
    method log_error (line 103) | fn log_error<D>(&self, message: &D)
    method log_warning (line 116) | fn log_warning<D>(&self, message: &D)
  method enabled (line 54) | fn enabled(&self, metadata: &Metadata) -> bool {
  method log (line 58) | fn log(&self, record: &Record) {
  method flush (line 78) | fn flush(&self) {}
  function wrap_content (line 139) | fn wrap_content<D>(prefix: &str, content: &D) -> String
  function level_from_env (line 161) | fn level_from_env() -> LevelFilter {

FILE: crates/volta-core/src/monitor.rs
  function send_events (line 14) | pub fn send_events(command: &str, events: &[Event]) {
  function write_events_file (line 34) | fn write_events_file(events_json: String) -> Option<PathBuf> {
  function spawn_process (line 64) | fn spawn_process(command: &str, tempfile_path: Option<PathBuf>) -> Optio...

FILE: crates/volta-core/src/platform/image.rs
  type Image (line 11) | pub struct Image {
    method bins (line 23) | fn bins(&self) -> Fallible<Vec<PathBuf>> {
    method path (line 51) | pub fn path(&self) -> Fallible<OsString> {
    method resolve_npm (line 62) | pub fn resolve_npm(&self) -> Fallible<Sourced<Version>> {

FILE: crates/volta-core/src/platform/mod.rs
  type Source (line 23) | pub enum Source {
    method fmt (line 38) | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
  type Sourced (line 48) | pub struct Sourced<T> {
  function with_default (line 54) | pub fn with_default(value: T) -> Self {
  function with_project (line 61) | pub fn with_project(value: T) -> Self {
  function with_binary (line 68) | pub fn with_binary(value: T) -> Self {
  function with_command_line (line 75) | pub fn with_command_line(value: T) -> Self {
  function as_ref (line 84) | pub fn as_ref(&self) -> Sourced<&T> {
  function cloned (line 96) | pub fn cloned(self) -> Sourced<T> {
  method clone (line 108) | fn clone(&self) -> Sourced<T> {
  type InheritOption (line 119) | pub enum InheritOption<T> {
  function map (line 128) | pub fn map<U, F>(self, f: F) -> InheritOption<U>
  function inherit (line 140) | pub fn inherit(self, other: Option<T>) -> Option<T> {
  function from (line 150) | fn from(base: InheritOption<T>) -> Option<T> {
  type PlatformSpec (line 158) | pub struct PlatformSpec {
    method as_default (line 167) | pub fn as_default(&self) -> Platform {
    method as_project (line 177) | pub fn as_project(&self) -> Platform {
    method as_binary (line 187) | pub fn as_binary(&self) -> Platform {
  type CliPlatform (line 199) | pub struct CliPlatform {
    method merge (line 208) | pub fn merge(self, base: Platform) -> Platform {
  function from (line 220) | fn from(base: CliPlatform) -> Option<Platform> {
  type Platform (line 235) | pub struct Platform {
    method current (line 252) | pub fn current(session: &mut Session) -> Fallible<Option<Self>> {
    method checkout (line 277) | pub fn checkout(self, session: &mut Session) -> Fallible<Image> {
  function build_path_error (line 306) | fn build_path_error() -> ErrorKind {

FILE: crates/volta-core/src/platform/system.rs
  type System (line 9) | pub struct System;
    method path (line 15) | pub fn path() -> Fallible<OsString> {

FILE: crates/volta-core/src/platform/tests.rs
  function test_paths (line 12) | fn test_paths() {
  function build_test_path (line 18) | fn build_test_path() -> String {
  function build_test_path (line 26) | fn build_test_path() -> String {
  function test_image_path (line 39) | fn test_image_path() {
  function test_system_path (line 149) | fn test_system_path() {
  function converts_some_value (line 169) | fn converts_some_value() {
  function leaves_none (line 176) | fn leaves_none() {
  function leaves_inherit (line 183) | fn leaves_inherit() {
  function keeps_some_value (line 194) | fn keeps_some_value() {
  function leaves_none (line 201) | fn leaves_none() {
  function inherits_from_base (line 208) | fn inherits_from_base() {
  constant NODE_VERSION (line 219) | const NODE_VERSION: Version = Version {
  constant NPM_VERSION (line 226) | const NPM_VERSION: Version = Version {
  constant YARN_VERSION (line 233) | const YARN_VERSION: Version = Version {
  function uses_node (line 246) | fn uses_node() {
  function inherits_node (line 268) | fn inherits_node() {
  function uses_npm (line 290) | fn uses_npm() {
  function inherits_npm (line 313) | fn inherits_npm() {
  function none_does_not_inherit_npm (line 336) | fn none_does_not_inherit_npm() {
  function uses_yarn (line 357) | fn uses_yarn() {
  function inherits_yarn (line 380) | fn inherits_yarn() {
  function none_does_not_inherit_yarn (line 403) | fn none_does_not_inherit_yarn() {
  function none_if_no_node (line 429) | fn none_if_no_node() {
  function uses_cli_node (line 443) | fn uses_cli_node() {
  function uses_cli_npm (line 459) | fn uses_cli_npm() {
  function no_npm (line 475) | fn no_npm() {
  function inherit_npm_becomes_none (line 489) | fn inherit_npm_becomes_none() {
  function uses_cli_yarn (line 503) | fn uses_cli_yarn() {
  function no_yarn (line 519) | fn no_yarn() {
  function inherit_yarn_becomes_none (line 533) | fn inherit_yarn_becomes_none() {

FILE: crates/volta-core/src/project/mod.rs
  type LazyProject (line 26) | pub struct LazyProject {
    method init (line 31) | pub fn init() -> Self {
    method get (line 37) | pub fn get(&self) -> Fallible<Option<&Project>> {
    method get_mut (line 42) | pub fn get_mut(&mut self) -> Fallible<Option<&mut Project>> {
  type Project (line 50) | pub struct Project {
    method for_current_dir (line 59) | fn for_current_dir() -> Fallible<Option<Self>> {
    method for_dir (line 67) | fn for_dir(base_dir: PathBuf) -> Fallible<Option<Self>> {
    method from_file (line 78) | fn from_file(manifest_file: PathBuf) -> Fallible<Self> {
    method manifest_file (line 123) | pub fn manifest_file(&self) -> &Path {
    method workspace_roots (line 128) | pub fn workspace_roots(&self) -> impl Iterator<Item = &Path> {
    method platform (line 136) | pub fn platform(&self) -> Option<&PlatformSpec> {
    method has_direct_dependency (line 141) | pub fn has_direct_dependency(&self, dependency: &str) -> bool {
    method has_direct_bin (line 146) | pub fn has_direct_bin(&self, bin_name: &OsStr) -> Fallible<bool> {
    method find_bin (line 159) | pub fn find_bin<P: AsRef<Path>>(&self, bin_name: P) -> Option<PathBuf> {
    method needs_yarn_run (line 175) | pub fn needs_yarn_run(&self) -> bool {
    method pin_node (line 186) | pub fn pin_node(&mut self, version: Version) -> Fallible<()> {
    method pin_npm (line 204) | pub fn pin_npm(&mut self, version: Option<Version>) -> Fallible<()> {
    method pin_pnpm (line 217) | pub fn pin_pnpm(&mut self, version: Option<Version>) -> Fallible<()> {
    method pin_yarn (line 233) | pub fn pin_yarn(&mut self, version: Option<Version>) -> Fallible<()> {
  function is_node_root (line 249) | fn is_node_root(dir: &Path) -> bool {
  function is_node_modules (line 253) | fn is_node_modules(dir: &Path) -> bool {
  function is_dependency (line 257) | fn is_dependency(dir: &Path) -> bool {
  function is_project_root (line 261) | fn is_project_root(dir: &Path) -> bool {
  function find_closest_root (line 266) | pub(crate) fn find_closest_root(mut dir: PathBuf) -> Option<PathBuf> {
  type PartialPlatform (line 276) | struct PartialPlatform {
    method merge (line 284) | fn merge(self, other: PartialPlatform) -> PartialPlatform {
  type Error (line 295) | type Error = VoltaError;
  method try_from (line 297) | fn try_from(partial: PartialPlatform) -> Fallible<PlatformSpec> {

FILE: crates/volta-core/src/project/serial.rs
  type DependencyMapIterator (line 15) | pub type DependencyMapIterator = std::iter::Chain<
  type Manifest (line 20) | pub(super) struct Manifest {
    method from_file (line 27) | pub fn from_file(file: &Path) -> Fallible<Self> {
  type ManifestKey (line 60) | pub(super) enum ManifestKey {
    method fmt (line 68) | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
  function update_manifest (line 83) | pub(super) fn update_manifest(
  type RawManifest (line 142) | struct RawManifest {
    method from_file (line 152) | fn from_file(package: &Path) -> Fallible<Self> {
  type ToolchainSpec (line 164) | struct ToolchainSpec {
    method parse_split (line 179) | fn parse_split(self) -> Fallible<(PartialPlatform, Option<PathBuf>)> {

FILE: crates/volta-core/src/project/tests.rs
  function fixture_path (line 5) | fn fixture_path(fixture_dirs: &[&str]) -> PathBuf {
  function test_find_closest_root_direct (line 20) | fn test_find_closest_root_direct() {
  function test_find_closest_root_ancestor (line 29) | fn test_find_closest_root_ancestor() {
  function test_find_closest_root_dependency (line 37) | fn test_find_closest_root_dependency() {
  function manifest_file (line 49) | fn manifest_file() {
  function workspace_roots (line 58) | fn workspace_roots() {
  function platform_simple (line 73) | fn platform_simple() {
  function platform_workspace (line 84) | fn platform_workspace() {
  function direct_dependencies_single (line 98) | fn direct_dependencies_single() {
  function direct_dependencies_workspace (line 113) | fn direct_dependencies_workspace() {
  function find_bin_single (line 132) | fn find_bin_single() {
  function find_bin_workspace (line 145) | fn find_bin_workspace() {
  function detects_workspace_cycles (line 185) | fn detects_workspace_cycles() {
  function project_does_not_need_yarn_run (line 225) | fn project_does_not_need_yarn_run() {
  function project_has_yarnrc_yml (line 232) | fn project_has_yarnrc_yml() {
  function project_has_pnp_js (line 239) | fn project_has_pnp_js() {
  function project_has_pnp_cjs (line 246) | fn project_has_pnp_cjs() {

FILE: crates/volta-core/src/run/binary.rs
  function command (line 17) | pub(super) fn command(exe: &OsStr, args: &[OsString], session: &mut Sess...
  function local_execution_context (line 88) | pub(super) fn local_execution_context(
  function default_execution_context (line 114) | pub(super) fn default_execution_context(
  type DefaultBinary (line 140) | pub struct DefaultBinary {
    method from_config (line 146) | pub fn from_config(bin_config: BinConfig, session: &mut Session) -> Fa...
    method from_name (line 173) | pub fn from_name(tool_name: &OsStr, session: &mut Session) -> Fallible...
  function shared_module_path (line 189) | fn shared_module_path() -> Fallible<OsString> {

FILE: crates/volta-core/src/run/executor.rs
  type Executor (line 22) | pub enum Executor {
    method envs (line 33) | pub fn envs<K, V, S>(&mut self, envs: &HashMap<K, V, S>)
    method cli_platform (line 55) | pub fn cli_platform(&mut self, cli: CliPlatform) {
    method execute (line 73) | pub fn execute(self, session: &mut Session) -> Fallible<ExitStatus> {
    method from (line 102) | fn from(mut executors: Vec<Executor>) -> Self {
    method from (line 203) | fn from(cmd: ToolCommand) -> Self {
    method from (line 300) | fn from(cmd: PackageInstallCommand) -> Self {
    method from (line 403) | fn from(cmd: PackageLinkCommand) -> Self {
    method from (line 493) | fn from(cmd: PackageUpgradeCommand) -> Self {
    method from (line 527) | fn from(cmd: InternalInstallCommand) -> Self {
    method from (line 560) | fn from(cmd: UninstallCommand) -> Self {
  type ToolCommand (line 115) | pub struct ToolCommand {
    method new (line 134) | pub fn new<E, A, S>(exe: E, args: A, platform: Option<Platform>, kind:...
    method envs (line 151) | pub fn envs<E, K, V>(&mut self, envs: E)
    method env (line 161) | pub fn env<K, V>(&mut self, key: K, value: V)
    method cli_platform (line 170) | pub fn cli_platform(&mut self, cli: CliPlatform) {
    method execute (line 178) | pub fn execute(mut self, session: &mut Session) -> Fallible<ExitStatus> {
  type ToolKind (line 122) | pub enum ToolKind {
  type PackageInstallCommand (line 212) | pub struct PackageInstallCommand {
    method new (line 222) | pub fn new<A, S>(args: A, platform: Platform, manager: PackageManager)...
    method for_npm_link (line 243) | pub fn for_npm_link<A, S>(args: A, platform: Platform, name: String) -...
    method envs (line 261) | pub fn envs<E, K, V>(&mut self, envs: E)
    method cli_platform (line 271) | pub fn cli_platform(&mut self, cli: CliPlatform) {
    method execute (line 277) | pub fn execute(mut self, session: &mut Session) -> Fallible<ExitStatus> {
  type PackageLinkCommand (line 309) | pub struct PackageLinkCommand {
    method new (line 319) | pub fn new<A, S>(args: A, platform: Platform, tool: String) -> Self
    method envs (line 335) | pub fn envs<E, K, V>(&mut self, envs: E)
    method cli_platform (line 345) | pub fn cli_platform(&mut self, cli: CliPlatform) {
    method execute (line 353) | pub fn execute(mut self, session: &mut Session) -> Fallible<ExitStatus> {
    method check_linked_package (line 373) | fn check_linked_package(&self, session: &mut Session) -> Fallible<()> {
  type PackageUpgradeCommand (line 412) | pub struct PackageUpgradeCommand {
    method new (line 422) | pub fn new<A, S>(
    method envs (line 449) | pub fn envs<E, K, V>(&mut self, envs: E)
    method cli_platform (line 459) | pub fn cli_platform(&mut self, cli: CliPlatform) {
    method execute (line 468) | pub fn execute(mut self, session: &mut Session) -> Fallible<ExitStatus> {
  type InternalInstallCommand (line 503) | pub struct InternalInstallCommand {
    method new (line 508) | pub fn new(tool: Spec) -> Self {
    method execute (line 513) | fn execute(self, session: &mut Session) -> Fallible<ExitStatus> {
  type UninstallCommand (line 536) | pub struct UninstallCommand {
    method new (line 541) | pub fn new(tool: Spec) -> Self {
    method execute (line 546) | fn execute(self) -> Fallible<ExitStatus> {

FILE: crates/volta-core/src/run/mod.rs
  constant RECURSION_ENV_VAR (line 34) | const RECURSION_ENV_VAR: &str = "_VOLTA_TOOL_RECURSION";
  constant VOLTA_BYPASS (line 35) | const VOLTA_BYPASS: &str = "VOLTA_BYPASS";
  function execute_shim (line 38) | pub fn execute_shim(session: &mut Session) -> Fallible<ExitStatus> {
  function execute_tool (line 47) | pub fn execute_tool<K, V, S>(
  function get_executor (line 70) | fn get_executor(
  function get_tool_name (line 106) | fn get_tool_name(args: &mut ArgsOs) -> Fallible<OsString> {
  function tool_name_from_file_name (line 113) | fn tool_name_from_file_name(file_name: &OsStr) -> OsString {
  function tool_name_from_file_name (line 118) | fn tool_name_from_file_name(file_name: &OsStr) -> OsString {
  function debug_no_platform (line 130) | fn debug_no_platform() {
  function debug_active_image (line 136) | fn debug_active_image(image: &Image) {
  function format_tool_version (line 163) | fn format_tool_version(version: &Sourced<Version>) -> String {

FILE: crates/volta-core/src/run/node.rs
  function command (line 11) | pub(super) fn command(args: &[OsString], session: &mut Session) -> Falli...
  function execution_context (line 23) | pub(super) fn execution_context(

FILE: crates/volta-core/src/run/npm.rs
  function command (line 22) | pub(super) fn command(args: &[OsString], session: &mut Session) -> Falli...
  function execution_context (line 66) | pub(super) fn execution_context(
  function current_project_name (line 87) | fn current_project_name(session: &mut Session) -> Option<String> {

FILE: crates/volta-core/src/run/npx.rs
  function command (line 21) | pub(super) fn command(args: &[OsString], session: &mut Session) -> Falli...
  function execution_context (line 33) | pub(super) fn execution_context(

FILE: crates/volta-core/src/run/parser.rs
  constant UNSAFE_GLOBAL (line 16) | const UNSAFE_GLOBAL: &str = "VOLTA_UNSAFE_GLOBAL";
  constant NPM_INSTALL_ALIASES (line 18) | const NPM_INSTALL_ALIASES: [&str; 12] = [
  constant NPM_UNINSTALL_ALIASES (line 23) | const NPM_UNINSTALL_ALIASES: [&str; 5] = ["un", "uninstall", "remove", "...
  constant NPM_LINK_ALIASES (line 25) | const NPM_LINK_ALIASES: [&str; 2] = ["link", "ln"];
  constant NPM_UPDATE_ALIASES (line 27) | const NPM_UPDATE_ALIASES: [&str; 4] = ["update", "udpate", "upgrade", "u...
  constant PNPM_UNINSTALL_ALIASES (line 30) | const PNPM_UNINSTALL_ALIASES: [&str; 4] = ["remove", "uninstall", "rm", ...
  constant PNPM_UPDATE_ALIASES (line 33) | const PNPM_UPDATE_ALIASES: [&str; 3] = ["update", "upgrade", "up"];
  constant PNPM_LINK_ALIASES (line 36) | const PNPM_LINK_ALIASES: [&str; 2] = ["link", "ln"];
  type CommandArg (line 38) | pub enum CommandArg<'a> {
  function for_npm (line 46) | pub fn for_npm<S>(args: &'a [S]) -> Self
  function for_pnpm (line 140) | pub fn for_pnpm<S>(args: &'a [S]) -> CommandArg<'a>
  function for_yarn (line 213) | pub fn for_yarn<S>(args: &'a [S]) -> Self
  type GlobalCommand (line 271) | pub enum GlobalCommand<'a> {
  function executor (line 278) | pub fn executor(self, platform: &PlatformSpec) -> Fallible<Executor> {
  type InstallArgs (line 288) | pub struct InstallArgs<'a> {
  function executor (line 303) | pub fn executor(self, platform_spec: &PlatformSpec) -> Fallible<Executor> {
  type UninstallArgs (line 328) | pub struct UninstallArgs<'a> {
  function executor (line 336) | pub fn executor(self) -> Fallible<Executor> {
  type UpgradeArgs (line 349) | pub struct UpgradeArgs<'a> {
  function executor (line 364) | pub fn executor(self, platform_spec: &PlatformSpec) -> Fallible<Executor> {
  function executor_all_packages (line 398) | fn executor_all_packages(self, platform_spec: &PlatformSpec) -> Fallible...
  type InterceptedCommand (line 418) | pub enum InterceptedCommand<'a> {
  type LinkArgs (line 424) | pub struct LinkArgs<'a> {
  function executor (line 432) | pub fn executor(self, platform: Platform, project_name: Option<String>) ...
  function has_global_without_prefix (line 472) | fn has_global_without_prefix<A>(args: &[A]) -> bool
  function is_flag (line 491) | fn is_flag<A>(arg: &A) -> bool
  function is_positional (line 501) | fn is_positional<A>(arg: &A) -> bool
  function arg_list (line 512) | fn arg_list<A, S>(args: A) -> Vec<OsString>
  function handles_global_install (line 525) | fn handles_global_install() {
  function handles_local_install (line 537) | fn handles_local_install() {
  function handles_global_uninstall (line 545) | fn handles_global_uninstall() {
  function handles_local_uninstall (line 555) | fn handles_local_uninstall() {
  function handles_multiple_install (line 563) | fn handles_multiple_install() {
  function handles_multiple_uninstall (line 584) | fn handles_multiple_uninstall() {
  function handles_bare_link (line 600) | fn handles_bare_link() {
  function handles_multiple_link (line 608) | fn handles_multiple_link() {
  function handles_bare_unlink (line 618) | fn handles_bare_unlink() {
  function handles_local_unlink (line 626) | fn handles_local_unlink() {
  function handles_global_aliases (line 634) | fn handles_global_aliases() {
  function handles_install_aliases (line 647) | fn handles_install_aliases() {
  function handles_uninstall_aliases (line 710) | fn handles_uninstall_aliases() {
  function handles_link_aliases (line 743) | fn handles_link_aliases() {
  function processes_flags (line 756) | fn processes_flags() {
  function skips_commands_with_prefix (line 791) | fn skips_commands_with_prefix() {
  function handles_global_add (line 839) | fn handles_global_add() {
  function handles_local_add (line 851) | fn handles_local_add() {
  function handles_global_remove (line 864) | fn handles_global_remove() {
  function handles_local_remove (line 874) | fn handles_local_remove() {
  function handles_multiple_add (line 887) | fn handles_multiple_add() {
  function handles_multiple_remove (line 905) | fn handles_multiple_remove() {
  function processes_flags (line 921) | fn processes_flags() {

FILE: crates/volta-core/src/run/pnpm.rs
  function command (line 10) | pub(super) fn command(args: &[OsString], session: &mut Session) -> Falli...
  function execution_context (line 35) | pub(super) fn execution_context(
  function validate_platform_pnpm (line 57) | fn validate_platform_pnpm(platform: &Platform) -> Fallible<()> {

FILE: crates/volta-core/src/run/yarn.rs
  function command (line 19) | pub(super) fn command(args: &[OsString], session: &mut Session) -> Falli...
  function execution_context (line 40) | pub(super) fn execution_context(
  function validate_platform_yarn (line 62) | fn validate_platform_yarn(platform: &Platform) -> Fallible<()> {

FILE: crates/volta-core/src/session.rs
  type ActivityKind (line 17) | pub enum ActivityKind {
  method fmt (line 44) | fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), fmt::Error> {
  type Session (line 82) | pub struct Session {
    method init (line 91) | pub fn init() -> Session {
    method project (line 101) | pub fn project(&self) -> Fallible<Option<&Project>> {
    method project_mut (line 106) | pub fn project_mut(&mut self) -> Fallible<Option<&mut Project>> {
    method default_platform (line 111) | pub fn default_platform(&self) -> Fallible<Option<&PlatformSpec>> {
    method project_platform (line 116) | pub fn project_platform(&self) -> Fallible<Option<&PlatformSpec>> {
    method toolchain (line 124) | pub fn toolchain(&self) -> Fallible<&Toolchain> {
    method toolchain_mut (line 129) | pub fn toolchain_mut(&mut self) -> Fallible<&mut Toolchain> {
    method hooks (line 134) | pub fn hooks(&self) -> Fallible<&HookConfig> {
    method add_event_start (line 138) | pub fn add_event_start(&mut self, activity_kind: ActivityKind) {
    method add_event_end (line 141) | pub fn add_event_end(&mut self, activity_kind: ActivityKind, exit_code...
    method add_event_tool_end (line 144) | pub fn add_event_tool_end(&mut self, activity_kind: ActivityKind, exit...
    method add_event_error (line 147) | pub fn add_event_error(&mut self, activity_kind: ActivityKind, error: ...
    method publish_to_event_log (line 151) | fn publish_to_event_log(self) {
    method exit (line 173) | pub fn exit(self, code: ExitCode) -> ! {
    method exit_tool (line 178) | pub fn exit_tool(self, code: i32) -> ! {
  function fixture_path (line 191) | fn fixture_path(fixture_dir: &str) -> PathBuf {
  function test_in_pinned_project (line 199) | fn test_in_pinned_project() {

FILE: crates/volta-core/src/shim.rs
  function regenerate_shims_for_dir (line 16) | pub fn regenerate_shims_for_dir(dir: &Path) -> Fallible<()> {
  function get_shim_list_deduped (line 28) | fn get_shim_list_deduped(dir: &Path) -> Fallible<HashSet<String>> {
  type ShimResult (line 54) | pub enum ShimResult {
  function delete (line 61) | pub fn delete(shim_name: &str) -> Fallible<ShimResult> {
  function create (line 100) | pub fn create(shim_name: &str) -> Fallible<ShimResult> {
  function entry_to_shim_name (line 121) | pub fn entry_to_shim_name((entry, metadata): (DirEntry, Metadata)) -> Op...
  constant SHIM_SCRIPT_CONTENTS (line 154) | const SHIM_SCRIPT_CONTENTS: &str = r#"@echo off
  constant GIT_BASH_SCRIPT_CONTENTS (line 158) | const GIT_BASH_SCRIPT_CONTENTS: &str = r#"#!/bin/bash
  function create (line 161) | pub fn create(shim_name: &str) -> Fallible<ShimResult> {
  function entry_to_shim_name (line 179) | pub fn entry_to_shim_name((entry, _): (DirEntry, Metadata)) -> Option<St...
  function delete_git_bash_script (line 191) | pub fn delete_git_bash_script(shim_name: &str) -> Fallible<()> {

FILE: crates/volta-core/src/signal.rs
  constant INTERRUPTED_EXIT_CODE (line 7) | const INTERRUPTED_EXIT_CODE: i32 = 130;
  function pass_control_to_shim (line 9) | pub fn pass_control_to_shim() {
  function setup_signal_handler (line 13) | pub fn setup_signal_handler() {

FILE: crates/volta-core/src/style.rs
  constant MAX_WIDTH (line 12) | pub const MAX_WIDTH: usize = 100;
  constant MAX_PROGRESS_WIDTH (line 13) | const MAX_PROGRESS_WIDTH: usize = 40;
  function success_prefix (line 16) | pub fn success_prefix() -> StyledObject<&'static str> {
  function note_prefix (line 21) | pub fn note_prefix() -> StyledObject<&'static str> {
  function format_error_cause (line 26) | pub(crate) fn format_error_cause(inner: &dyn Error) -> String {
  function action_str (line 36) | fn action_str(origin: Origin) -> &'static str {
  function tool_version (line 43) | pub fn tool_version<N, V>(name: N, version: V) -> String
  function text_width (line 52) | pub fn text_width() -> Option<usize> {
  function progress_bar (line 60) | pub fn progress_bar(origin: Origin, details: &str, len: u64) -> Progress...

FILE: crates/volta-core/src/sync.rs
  type LockState (line 44) | struct LockState {
  constant LOCK_FILE (line 49) | const LOCK_FILE: &str = "volta.lock";
  type VoltaLock (line 56) | pub struct VoltaLock {
    method acquire (line 62) | pub fn acquire() -> Fallible<Self> {
  method drop (line 106) | fn drop(&mut self) {

FILE: crates/volta-core/src/tool/mod.rs
  function debug_already_fetched (line 32) | fn debug_already_fetched<T: Display>(tool: T) {
  function info_installed (line 36) | fn info_installed<T: Display>(tool: T) {
  function info_fetched (line 40) | fn info_fetched<T: Display>(tool: T) {
  function info_pinned (line 44) | fn info_pinned<T: Display>(tool: T) {
  function info_project_version (line 48) | fn info_project_version<P, D>(project_version: P, default_version: D)
  type Tool (line 61) | pub trait Tool: Display {
    method fetch (line 63) | fn fetch(self: Box<Self>, session: &mut Session) -> Fallible<()>;
    method install (line 65) | fn install(self: Box<Self>, session: &mut Session) -> Fallible<()>;
    method pin (line 67) | fn pin(self: Box<Self>, session: &mut Session) -> Fallible<()>;
  type Spec (line 73) | pub enum Spec {
    method resolve (line 83) | pub fn resolve(self, session: &mut Session) -> Fallible<Box<dyn Tool>> {
    method uninstall (line 122) | pub fn uninstall(self) -> Fallible<()> {
    method name (line 151) | pub fn name(&self) -> &str {
  method fmt (line 163) | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
  type FetchStatus (line 178) | enum FetchStatus {
  function check_fetched (line 191) | fn check_fetched<F>(already_fetched: F) -> Fallible<FetchStatus>
  function download_tool_error (line 214) | fn download_tool_error(tool: Spec, from_url: impl AsRef<str>) -> impl Fn...
  function registry_fetch_error (line 219) | fn registry_fetch_error(
  function check_shim_reachable (line 238) | pub fn check_shim_reachable(shim_name: &str) {
  function find_expected_shim_dir (line 270) | fn find_expected_shim_dir(_shim_name: &str) -> Option<PathBuf> {
  function find_expected_shim_dir (line 282) | fn find_expected_shim_dir(shim_name: &str) -> Option<PathBuf> {

FILE: crates/volta-core/src/tool/node/fetch.rs
  function npm_manifest_path (line 37) | fn npm_manifest_path(version: &Version) -> PathBuf {
  function fetch (line 50) | pub fn fetch(version: &Version, hooks: Option<&ToolHooks<Node>>) -> Fall...
  function unpack_archive (line 91) | fn unpack_archive(archive: Box<dyn Archive>, version: &Version) -> Falli...
  function load_cached_distro (line 143) | fn load_cached_distro(file: &Path) -> Option<Box<dyn Archive>> {
  function determine_remote_url (line 153) | fn determine_remote_url(version: &Version, hooks: Option<&ToolHooks<Node...
  function fetch_remote_distro (line 173) | fn fetch_remote_distro(
  type Manifest (line 187) | struct Manifest {
    method version (line 193) | fn version(path: &Path) -> Fallible<Version> {
  function load_default_npm_version (line 202) | pub fn load_default_npm_version(node: &Version) -> Fallible<Version> {
  function save_default_npm_version (line 212) | fn save_default_npm_version(node: &Version, npm: &Version) -> Fallible<(...

FILE: crates/volta-core/src/tool/node/metadata.rs
  type NodeIndex (line 14) | pub struct NodeIndex {
    method from (line 40) | fn from(raw: RawNodeIndex) -> NodeIndex {
  type NodeEntry (line 19) | pub struct NodeEntry {
  type RawNodeIndex (line 25) | pub struct RawNodeIndex(Vec<RawNodeEntry>);
  type RawNodeEntry (line 28) | pub struct RawNodeEntry {
  function lts_version_serde (line 81) | fn lts_version_serde<'de, D>(deserializer: D) -> Result<bool, D::Error>

FILE: crates/volta-core/src/tool/node/mod.rs
  type NodeVersion (line 121) | pub struct NodeVersion {
  method fmt (line 129) | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
  type Node (line 140) | pub struct Node {
    method new (line 145) | pub fn new(version: Version) -> Self {
    method archive_basename (line 153) | pub fn archive_basename(version: &Version) -> String {
    method archive_basename (line 158) | pub fn archive_basename(version: &Version) -> String {
    method archive_basename (line 174) | pub fn archive_basename(version: &Version) -> String {
    method archive_filename (line 189) | pub fn archive_filename(version: &Version) -> String {
    method ensure_fetched (line 197) | pub(crate) fn ensure_fetched(&self, session: &mut Session) -> Fallible...
  method fetch (line 214) | fn fetch(self: Box<Self>, session: &mut Session) -> Fallible<()> {
  method install (line 220) | fn install(self: Box<Self>, session: &mut Session) -> Fallible<()> {
  method pin (line 254) | fn pin(self: Box<Self>, session: &mut Session) -> Fallible<()> {
  method fmt (line 288) | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
  function test_node_archive_basename (line 298) | fn test_node_archive_basename() {
  function test_node_archive_filename (line 306) | fn test_node_archive_filename() {
  function test_fallback_node_archive_basename (line 318) | fn test_fallback_node_archive_basename() {
  function test_fallback_node_archive_basename (line 330) | fn test_fallback_node_archive_basename() {
  function test_fallback_node_archive_filename (line 342) | fn test_fallback_node_archive_filename() {
  function test_fallback_node_archive_filename (line 354) | fn test_fallback_node_archive_filename() {

FILE: crates/volta-core/src/tool/node/resolve.rs
  function resolve (line 44) | pub fn resolve(matching: VersionSpec, session: &mut Session) -> Fallible...
  function resolve_latest (line 58) | fn resolve_latest(hooks: Option<&ToolHooks<Node>>) -> Fallible<Version> {
  function resolve_lts (line 86) | fn resolve_lts(hooks: Option<&ToolHooks<Node>>) -> Fallible<Version> {
  function resolve_semver (line 111) | fn resolve_semver(matching: Range, hooks: Option<&ToolHooks<Node>>) -> F...
  function match_node_version (line 141) | fn match_node_version(
  function read_cached_opt (line 153) | fn read_cached_opt(url: &str) -> Fallible<Option<RawNodeIndex>> {
  function max_age (line 184) | fn max_age(headers: &HeaderMap) -> Duration {
  function resolve_node_versions (line 192) | fn resolve_node_versions(url: &str) -> Fallible<RawNodeIndex> {

FILE: crates/volta-core/src/tool/npm/fetch.rs
  function fetch (line 20) | pub fn fetch(version: &Version, hooks: Option<&ToolHooks<Npm>>) -> Falli...
  function unpack_archive (line 58) | fn unpack_archive(archive: Box<dyn Archive>, version: &Version) -> Falli...
  function load_cached_distro (line 109) | fn load_cached_distro(file: &Path) -> Option<Box<dyn Archive>> {
  function determine_remote_url (line 119) | fn determine_remote_url(version: &Version, hooks: Option<&ToolHooks<Npm>...
  function fetch_remote_distro (line 135) | fn fetch_remote_distro(
  function overwrite_launcher (line 148) | fn overwrite_launcher(base_path: &Path, tool: &str) -> Fallible<()> {
  function overwrite_cmd_launcher (line 174) | fn overwrite_cmd_launcher(base_path: &Path, tool: &str) -> Fallible<()> {

FILE: crates/volta-core/src/tool/npm/mod.rs
  type Npm (line 22) | pub struct Npm {
    method new (line 27) | pub fn new(version: Version) -> Self {
    method archive_basename (line 31) | pub fn archive_basename(version: &str) -> String {
    method archive_filename (line 35) | pub fn archive_filename(version: &str) -> String {
    method ensure_fetched (line 39) | pub(crate) fn ensure_fetched(&self, session: &mut Session) -> Fallible...
  method fetch (line 51) | fn fetch(self: Box<Self>, session: &mut Session) -> Fallible<()> {
  method install (line 57) | fn install(self: Box<Self>, session: &mut Session) -> Fallible<()> {
  method pin (line 76) | fn pin(self: Box<Self>, session: &mut Session) -> Fallible<()> {
  method fmt (line 93) | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
  type BundledNpm (line 99) | pub struct BundledNpm;
  method fetch (line 102) | fn fetch(self: Box<Self>, _session: &mut Session) -> Fallible<()> {
  method install (line 107) | fn install(self: Box<Self>, session: &mut Session) -> Fallible<()> {
  method pin (line 138) | fn pin(self: Box<Self>, session: &mut Session) -> Fallible<()> {
  method fmt (line 175) | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
  function test_npm_archive_basename (line 185) | fn test_npm_archive_basename() {
  function test_npm_archive_filename (line 190) | fn test_npm_archive_filename() {

FILE: crates/volta-core/src/tool/npm/resolve.rs
  function resolve (line 14) | pub fn resolve(matching: VersionSpec, session: &mut Session) -> Fallible...
  function fetch_npm_index (line 27) | fn fetch_npm_index(hooks: Option<&ToolHooks<Npm>>) -> Fallible<(String, ...
  function resolve_tag (line 42) | fn resolve_tag(tag: &str, hooks: Option<&ToolHooks<Npm>>) -> Fallible<Ve...
  function resolve_semver (line 57) | fn resolve_semver(matching: Range, hooks: Option<&ToolHooks<Npm>>) -> Fa...

FILE: crates/volta-core/src/tool/package/configure.rs
  function parse_manifest (line 12) | pub(super) fn parse_manifest(
  function write_config_and_shims (line 24) | pub(super) fn write_config_and_shims(
  function validate_bins (line 69) | fn validate_bins(package_name: &str, manifest: &PackageManifest) -> Fall...

FILE: crates/volta-core/src/tool/package/install.rs
  function run_global_install (line 15) | pub(super) fn run_global_install(

FILE: crates/volta-core/src/tool/package/manager.rs
  type PackageManager (line 13) | pub enum PackageManager {
    method source_dir (line 22) | pub fn source_dir(self, package_root: PathBuf) -> PathBuf {
    method source_root (line 32) | pub fn source_root(self, package_root: PathBuf) -> PathBuf {
    method source_root (line 50) | pub fn source_root(self, package_root: PathBuf) -> PathBuf {
    method binary_dir (line 75) | pub fn binary_dir(self, package_root: PathBuf) -> PathBuf {
    method binary_dir (line 86) | pub fn binary_dir(self, package_root: PathBuf) -> PathBuf {
    method setup_global_command (line 101) | pub fn setup_global_command(self, command: &mut Command, package_root:...
    method get_installed_package (line 148) | pub(super) fn get_installed_package(self, package_root: PathBuf) -> Op...
  function get_npm_package_name (line 162) | fn get_npm_package_name(mut source_dir: PathBuf) -> Option<String> {
  function get_single_directory_name (line 179) | fn get_single_directory_name(parent_dir: &Path) -> Option<String> {
  function get_pnpm_or_yarn_package_name (line 202) | fn get_pnpm_or_yarn_package_name(source_root: PathBuf) -> Option<String> {

FILE: crates/volta-core/src/tool/package/metadata.rs
  type PackageConfig (line 18) | pub struct PackageConfig {
    method from_file (line 35) | pub fn from_file<P>(file: P) -> Fallible<Self>
    method from_file_if_exists (line 45) | pub fn from_file_if_exists<P>(file: P) -> Fallible<Option<Self>>
    method write (line 69) | pub fn write(self) -> Fallible<()> {
  type BinConfig (line 92) | pub struct BinConfig {
    method from_file (line 109) | pub fn from_file<P>(file: P) -> Fallible<Self>
    method from_file_if_exists (line 119) | pub fn from_file_if_exists<P>(file: P) -> Fallible<Option<Self>>
    method write (line 143) | pub fn write(self) -> Fallible<()> {
  type RawPlatformSpec (line 163) | struct RawPlatformSpec {
  type PackageManifest (line 184) | pub struct PackageManifest {
    method for_dir (line 197) | pub fn for_dir(package: &str, package_root: &Path) -> Fallible<Self> {
  type GlobalYarnManifest (line 228) | pub(super) struct GlobalYarnManifest {
  function deserialize (line 238) | pub fn deserialize<'de, D>(deserializer: D) -> Result<Vec<String>, D::Er...
  type BinMapVisitor (line 245) | struct BinMapVisitor;
    type Value (line 248) | type Value = Vec<String>;
    method expecting (line 250) | fn expecting(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
    method visit_str (line 255) | fn visit_str<E>(self, _path: &str) -> Result<Self::Value, E>
    method visit_map (line 265) | fn visit_map<M>(self, mut access: M) -> Result<Self::Value, M::Error>
  function default_binary_name (line 288) | fn default_binary_name(package_name: &str) -> String {
  function default_binary_uses_full_name_if_unscoped (line 315) | fn default_binary_uses_full_name_if_unscoped() {
  function default_binary_removes_scope (line 320) | fn default_binary_removes_scope() {

FILE: crates/volta-core/src/tool/package/mod.rs
  type Package (line 30) | pub struct Package {
    method new (line 37) | pub fn new(name: String, version: VersionSpec) -> Fallible<Self> {
    method run_install (line 47) | pub fn run_install(&self, platform_image: &Image) -> Fallible<()> {
    method complete_install (line 55) | pub fn complete_install(self, image: &Image) -> Fallible<PackageManife...
  method fetch (line 69) | fn fetch(self: Box<Self>, _session: &mut Session) -> Fallible<()> {
  method install (line 76) | fn install(self: Box<Self>, session: &mut Session) -> Fallible<()> {
  method pin (line 108) | fn pin(self: Box<Self>, _session: &mut Session) -> Fallible<()> {
  method fmt (line 114) | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
  type DirectInstall (line 129) | pub struct DirectInstall {
    method new (line 136) | pub fn new(manager: PackageManager) -> Fallible<Self> {
    method with_name (line 146) | pub fn with_name(manager: PackageManager, name: String) -> Fallible<Se...
    method setup_command (line 156) | pub fn setup_command(&self, command: &mut Command) {
    method complete_install (line 161) | pub fn complete_install(self, image: &Image) -> Fallible<()> {
  type InPlaceUpgrade (line 182) | pub struct InPlaceUpgrade {
    method new (line 189) | pub fn new(package: String, manager: PackageManager) -> Fallible<Self> {
    method check_upgraded_package (line 202) | pub fn check_upgraded_package(&self) -> Fallible<()> {
    method setup_command (line 221) | pub fn setup_command(&self, command: &mut Command) {
    method complete_upgrade (line 226) | pub fn complete_upgrade(self, image: &Image) -> Fallible<()> {
  type NeedsScope (line 235) | enum NeedsScope {
    method from (line 241) | fn from(value: bool) -> Self {
  function setup_staging_directory (line 252) | fn setup_staging_directory(manager: PackageManager, needs_scope: NeedsSc...
  function persist_install (line 286) | fn persist_install<V>(package_name: &str, package_version: V, staging_di...
  function link_package_to_shared_dir (line 308) | fn link_package_to_shared_dir(package_name: &str, manager: PackageManage...

FILE: crates/volta-core/src/tool/package/uninstall.rs
  function uninstall (line 19) | pub fn uninstall(name: &str) -> Fallible<()> {
  function remove_config_and_shim (line 66) | fn remove_config_and_shim(bin_name: &str, pkg_name: &str) -> Fallible<()> {
  function binaries_from_package (line 79) | fn binaries_from_package(package: &str) -> Fallible<Vec<String>> {
  function remove_shared_link_dir (line 100) | fn remove_shared_link_dir(name: &str) -> Fallible<()> {

FILE: crates/volta-core/src/tool/pnpm/fetch.rs
  function fetch (line 20) | pub fn fetch(version: &Version, hooks: Option<&ToolHooks<Pnpm>>) -> Fall...
  function unpack_archive (line 60) | fn unpack_archive(archive: Box<dyn Archive>, version: &Version) -> Falli...
  function load_cached_distro (line 111) | fn load_cached_distro(file: &Path) -> Option<Box<dyn Archive>> {
  function determine_remote_url (line 121) | fn determine_remote_url(version: &Version, hooks: Option<&ToolHooks<Pnpm...
  function fetch_remote_distro (line 137) | fn fetch_remote_distro(
  function write_launcher (line 150) | fn write_launcher(base_path: &Path, tool: &str) -> Fallible<()> {
  function write_cmd_launcher (line 175) | fn write_cmd_launcher(base_path: &Path, tool: &str) -> Fallible<()> {

FILE: crates/volta-core/src/tool/pnpm/mod.rs
  type Pnpm (line 21) | pub struct Pnpm {
    method new (line 26) | pub fn new(version: Version) -> Self {
    method archive_basename (line 30) | pub fn archive_basename(version: &str) -> String {
    method archive_filename (line 34) | pub fn archive_filename(version: &str) -> String {
    method ensure_fetched (line 38) | pub(crate) fn ensure_fetched(&self, session: &mut Session) -> Fallible...
  method fetch (line 50) | fn fetch(self: Box<Self>, session: &mut Session) -> Fallible<()> {
  method install (line 57) | fn install(self: Box<Self>, session: &mut Session) -> Fallible<()> {
  method pin (line 77) | fn pin(self: Box<Self>, session: &mut Session) -> Fallible<()> {
  method fmt (line 94) | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
  function test_pnpm_archive_basename (line 104) | fn test_pnpm_archive_basename() {
  function test_pnpm_archive_filename (line 109) | fn test_pnpm_archive_filename() {

FILE: crates/volta-core/src/tool/pnpm/resolve.rs
  function resolve (line 11) | pub fn resolve(matching: VersionSpec, session: &mut Session) -> Fallible...
  function resolve_tag (line 21) | fn resolve_tag(tag: &str, hooks: Option<&ToolHooks<Pnpm>>) -> Fallible<V...
  function resolve_semver (line 36) | fn resolve_semver(matching: Range, hooks: Option<&ToolHooks<Pnpm>>) -> F...
  function fetch_pnpm_index (line 60) | fn fetch_pnpm_index(hooks: Option<&ToolHooks<Pnpm>>) -> Fallible<(String...

FILE: crates/volta-core/src/tool/registry.rs
  constant NPM_ABBREVIATED_ACCEPT_HEADER (line 17) | pub const NPM_ABBREVIATED_ACCEPT_HEADER: &str =
  function fetch_npm_registry (line 38) | pub fn fetch_npm_registry(url: String, name: &str) -> Fallible<(String, ...
  function public_registry_package (line 51) | pub fn public_registry_package(package: &str, version: &str) -> String {
  function scoped_public_registry_package (line 62) | pub fn scoped_public_registry_package(scope: &str, package: &str, versio...
  function find_unpack_dir (line 75) | pub fn find_unpack_dir(in_dir: &Path) -> Fallible<PathBuf> {
  type PackageDetails (line 92) | pub struct PackageDetails {
  type PackageIndex (line 97) | pub struct PackageIndex {
    method from (line 132) | fn from(serial: RawPackageMetadata) -> PackageIndex {
  type RawPackageMetadata (line 107) | pub struct RawPackageMetadata {
  type RawPackageVersionInfo (line 118) | pub struct RawPackageVersionInfo {
  type RawDistInfo (line 126) | pub struct RawDistInfo {

FILE: crates/volta-core/src/tool/serial.rs
  method from_str_and_version (line 17) | pub fn from_str_and_version(tool_name: &str, version: VersionSpec) -> Se...
  method try_from_str (line 28) | pub fn try_from_str(tool_spec: &str) -> Fallible<Self> {
  method from_strings (line 71) | pub fn from_strings<T>(tool_strs: &[T], action: &str) -> Fallible<Vec<Sp...
  method check_args (line 89) | fn check_args<T>(args: &[T], action: &str) -> Fallible<()>
  method sort_comparator (line 137) | fn sort_comparator(left: &Spec, right: &Spec) -> Ordering {
  function is_version_like (line 159) | fn is_version_like(value: &str) -> bool {
  constant LTS (line 177) | const LTS: &str = "lts";
  constant LATEST (line 178) | const LATEST: &str = "latest";
  constant MAJOR (line 179) | const MAJOR: &str = "3";
  constant MINOR (line 180) | const MINOR: &str = "3.0";
  constant PATCH (line 181) | const PATCH: &str = "3.0.0";
  constant BETA (line 182) | const BETA: &str = "beta";
  function parses_bare_node (line 192) | fn parses_bare_node() {
  function parses_node_with_valid_versions (line 200) | fn parses_node_with_valid_versions() {
  function parses_bare_yarn (line 230) | fn parses_bare_yarn() {
  function parses_yarn_with_valid_versions (line 238) | fn parses_yarn_with_valid_versions() {
  function parses_bare_packages (line 263) | fn parses_bare_packages() {
  function parses_namespaced_packages (line 272) | fn parses_namespaced_packages() {
  function parses_bare_packages_with_valid_versions (line 281) | fn parses_bare_packages_with_valid_versions() {
  function parses_namespaced_packages_with_valid_versions (line 328) | fn parses_namespaced_packages_with_valid_versions() {
  function special_cases_just_number (line 382) | fn special_cases_just_number() {
  function special_cases_tool_space_number (line 399) | fn special_cases_tool_space_number() {
  function leaves_other_scenarios_alone (line 418) | fn leaves_other_scenarios_alone() {
  function sorts_node_npm_yarn_to_front (line 471) | fn sorts_node_npm_yarn_to_front() {
  function keeps_package_order_unchanged (line 491) | fn keeps_package_order_unchanged() {

FILE: crates/volta-core/src/tool/yarn/fetch.rs
  function fetch (line 22) | pub fn fetch(version: &Version, hooks: Option<&YarnHooks>) -> Fallible<(...
  function unpack_archive (line 62) | fn unpack_archive(archive: Box<dyn Archive>, version: &Version) -> Falli...
  function load_cached_distro (line 107) | fn load_cached_distro(file: &Path) -> Option<Box<dyn Archive>> {
  function determine_remote_url (line 117) | fn determine_remote_url(version: &Version, hooks: Option<&YarnHooks>) ->...
  function fetch_remote_distro (line 143) | fn fetch_remote_distro(
  function ensure_bin_is_executable (line 155) | fn ensure_bin_is_executable(unpack_dir: &Path, tool: &str) -> Fallible<(...

FILE: crates/volta-core/src/tool/yarn/metadata.rs
  type YarnIndex (line 8) | pub struct YarnIndex {
    method from (line 46) | fn from(raw: RawYarnIndex) -> YarnIndex {
  type RawYarnIndex (line 13) | pub struct RawYarnIndex(Vec<RawYarnEntry>);
  type RawYarnEntry (line 16) | pub struct RawYarnEntry {
    method is_full_release (line 31) | fn is_full_release(&self) -> bool {
  type RawYarnAsset (line 40) | pub struct RawYarnAsset {

FILE: crates/volta-core/src/tool/yarn/mod.rs
  type Yarn (line 21) | pub struct Yarn {
    method new (line 26) | pub fn new(version: Version) -> Self {
    method archive_basename (line 30) | pub fn archive_basename(version: &str) -> String {
    method archive_filename (line 34) | pub fn archive_filename(version: &str) -> String {
    method ensure_fetched (line 38) | pub(crate) fn ensure_fetched(&self, session: &mut Session) -> Fallible...
  method fetch (line 50) | fn fetch(self: Box<Self>, session: &mut Session) -> Fallible<()> {
  method install (line 56) | fn install(self: Box<Self>, session: &mut Session) -> Fallible<()> {
  method pin (line 75) | fn pin(self: Box<Self>, session: &mut Session) -> Fallible<()> {
  method fmt (line 92) | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
  function test_yarn_archive_basename (line 102) | fn test_yarn_archive_basename() {
  function test_yarn_archive_filename (line 107) | fn test_yarn_archive_filename() {

FILE: crates/volta-core/src/tool/yarn/resolve.rs
  function resolve (line 17) | pub fn resolve(matching: VersionSpec, session: &mut Session) -> Fallible...
  function resolve_tag (line 27) | fn resolve_tag(tag: VersionTag, hooks: Option<&YarnHooks>) -> Fallible<V...
  function resolve_semver (line 55) | fn resolve_semver(matching: Range, hooks: Option<&YarnHooks>) -> Fallibl...
  function fetch_yarn_index (line 76) | fn fetch_yarn_index(package: &str) -> Fallible<(String, PackageIndex)> {
  function resolve_custom_tag (line 81) | fn resolve_custom_tag(tag: String) -> Fallible<Version> {
  function resolve_latest_legacy (line 107) | fn resolve_latest_legacy(url: String) -> Fallible<Version> {
  function resolve_semver_from_registry (line 120) | fn resolve_semver_from_registry(matching: Range) -> Fallible<Version> {
  function resolve_semver_legacy (line 176) | fn resolve_semver_legacy(matching: Range, url: String) -> Fallible<Versi...
  function resolve_semver_npm (line 203) | fn resolve_semver_npm(matching: Range, url: String) -> Fallible<Version> {

FILE: crates/volta-core/src/toolchain/mod.rs
  type LazyToolchain (line 15) | pub struct LazyToolchain {
    method init (line 21) | pub fn init() -> Self {
    method get (line 28) | pub fn get(&self) -> Fallible<&Toolchain> {
    method get_mut (line 33) | pub fn get_mut(&mut self) -> Fallible<&mut Toolchain> {
  type Toolchain (line 39) | pub struct Toolchain {
    method current (line 44) | fn current() -> Fallible<Toolchain> {
    method platform (line 59) | pub fn platform(&self) -> Option<&PlatformSpec> {
    method set_active_node (line 64) | pub fn set_active_node(&mut self, node_version: &Version) -> Fallible<...
    method set_active_yarn (line 93) | pub fn set_active_yarn(&mut self, yarn: Option<Version>) -> Fallible<(...
    method set_active_pnpm (line 110) | pub fn set_active_pnpm(&mut self, pnpm: Option<Version>) -> Fallible<(...
    method set_active_npm (line 127) | pub fn set_active_npm(&mut self, npm: Option<Version>) -> Fallible<()> {
    method save (line 140) | pub fn save(&self) -> Fallible<()> {

FILE: crates/volta-core/src/toolchain/serial.rs
  type NodeVersion (line 8) | pub struct NodeVersion {
  type Platform (line 16) | pub struct Platform {
    method of (line 28) | pub fn of(source: &PlatformSpec) -> Self {
    method into_json (line 40) | pub fn into_json(self) -> Fallible<String> {
    type Error (line 46) | type Error = VoltaError;
    method try_from (line 47) | fn try_from(src: String) -> Fallible<Self> {
  function from (line 59) | fn from(platform: Platform) -> Option<PlatformSpec> {
  constant BASIC_JSON_STR (line 81) | const BASIC_JSON_STR: &str = r#"{
  function test_from_json (line 91) | fn test_from_json() {
  function test_from_json_empty_string (line 106) | fn test_from_json_empty_string() {
  function test_into_json (line 118) | fn test_into_json() {

FILE: crates/volta-core/src/version/mod.rs
  type VersionSpec (line 11) | pub enum VersionSpec {
    method fmt (line 40) | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
  type VersionTag (line 28) | pub enum VersionTag {
    method fmt (line 51) | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
  type Err (line 61) | type Err = VoltaError;
  method from_str (line 63) | fn from_str(s: &str) -> Fallible<Self> {
  type Err (line 75) | type Err = VoltaError;
  method from_str (line 77) | fn from_str(s: &str) -> Fallible<Self> {
  function parse_requirements (line 88) | pub fn parse_requirements(s: impl AsRef<str>) -> Fallible<Range> {
  function parse_version (line 94) | pub fn parse_version(s: impl AsRef<str>) -> Fallible<Version> {
  function trim_version (line 101) | fn trim_version(s: &str) -> &str {
  type VersionVisitor (line 117) | struct VersionVisitor;
    type Value (line 120) | type Value = Version;
    method expecting (line 122) | fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
    method visit_str (line 127) | fn visit_str<E>(self, value: &str) -> Result<Self::Value, E>
  function serialize (line 135) | pub fn serialize<S>(version: &Version, s: S) -> Result<S::Ok, S::Error>
  function deserialize (line 142) | pub fn deserialize<'de, D>(deserializer: D) -> Result<Version, D::Error>
  function serialize (line 157) | pub fn serialize<S>(version: &Option<Version>, s: S) -> Result<S::Ok, S:...
  function deserialize (line 167) | pub fn deserialize<'de, D>(deserializer: D) -> Result<Option<Version>, D...
  type Wrapper (line 190) | struct Wrapper(#[serde(deserialize_with = "version_serde::deserialize")]...
  function deserialize (line 192) | pub fn deserialize<'de, D>(deserializer: D) -> Result<HashMap<String, Ve...

FILE: crates/volta-core/src/version/serial.rs
  function parse_requirements (line 14) | pub fn parse_requirements(src: &str) -> Result<Range, SemverError> {
  function test_parse_requirements (line 27) | fn test_parse_requirements() {

FILE: crates/volta-layout-macro/src/ast.rs
  type Result (line 8) | pub(crate) type Result<T> = ::std::result::Result<T, TokenStream>;
  type Ast (line 20) | pub(crate) struct Ast {
    method compile (line 37) | pub(crate) fn compile(self) -> TokenStream {
  method parse (line 25) | fn parse(input: ParseStream) -> parse::Result<Self> {
  type LayoutStruct (line 56) | pub(crate) struct LayoutStruct {
    method flatten (line 81) | fn flatten(self) -> Result<Ir> {
  method parse (line 64) | fn parse(input: ParseStream) -> parse::Result<Self> {
  type Directory (line 107) | struct Directory {
    method flatten (line 129) | fn flatten(self, results: &mut Ir, context: Vec<LitStr>) -> Result<()> {
  method parse (line 112) | fn parse(input: ParseStream) -> parse::Result<Self> {
  type EntryKind (line 121) | enum EntryKind {
  type FieldPrefix (line 234) | struct FieldPrefix {
  method parse (line 240) | fn parse(input: ParseStream) -> parse::Result<Self> {
  type FieldContents (line 249) | enum FieldContents {
  method parse (line 258) | fn parse(input: ParseStream) -> parse::Result<Self> {

FILE: crates/volta-layout-macro/src/ir.rs
  type Ir (line 24) | pub(crate) struct Ir {
    method dir_names (line 34) | fn dir_names(&self) -> impl Iterator<Item = &Ident> {
    method file_names (line 38) | fn file_names(&self) -> impl Iterator<Item = &Ident> {
    method exe_names (line 42) | fn exe_names(&self) -> impl Iterator<Item = &Ident> {
    method field_names (line 46) | fn field_names(&self) -> impl Iterator<Item = &Ident> {
    method to_struct_decl (line 53) | fn to_struct_decl(&self) -> TokenStream {
    method to_create_method (line 74) | fn to_create_method(&self) -> TokenStream {
    method to_item_methods (line 89) | fn to_item_methods(&self) -> TokenStream {
    method to_ctor (line 116) | fn to_ctor(&self) -> TokenStream {
    method codegen (line 150) | pub(crate) fn codegen(&self) -> TokenStream {
  type Entry (line 165) | pub(crate) struct Entry {
    method to_normal_init (line 172) | fn to_normal_init(&self, root: &Ident) -> TokenStream {
    method to_exe_init (line 188) | fn to_exe_init(&self, root: &Ident) -> TokenStream {

FILE: crates/volta-layout-macro/src/lib.rs
  function layout (line 54) | pub fn layout(input: TokenStream) -> TokenStream {

FILE: crates/volta-layout/src/lib.rs
  function executable (line 10) | fn executable(name: &str) -> String {

FILE: crates/volta-layout/src/v0.rs
  method package_distro_file (line 43) | pub fn package_distro_file(&self, name: &str, version: &str) -> PathBuf {
  method package_distro_shasum (line 50) | pub fn package_distro_shasum(&self, name: &str, version: &str) -> PathBuf {
  method node_image_dir (line 57) | pub fn node_image_dir(&self, node: &str, npm: &str) -> PathBuf {
  method yarn_image_dir (line 61) | pub fn yarn_image_dir(&self, version: &str) -> PathBuf {
  method yarn_image_bin_dir (line 65) | pub fn yarn_image_bin_dir(&self, version: &str) -> PathBuf {
  method package_image_dir (line 69) | pub fn package_image_dir(&self, name: &str, version: &str) -> PathBuf {
  method default_package_config_file (line 73) | pub fn default_package_config_file(&self, package_name: &str) -> PathBuf {
  method default_tool_bin_config (line 80) | pub fn default_tool_bin_config(&self, bin_name: &str) -> PathBuf {
  method node_npm_version_file (line 84) | pub fn node_npm_version_file(&self, version: &str) -> PathBuf {
  method shim_file (line 91) | pub fn shim_file(&self, toolname: &str) -> PathBuf {
  method shim_git_bash_script_file (line 98) | pub fn shim_git_bash_script_file(&self, toolname: &str) -> PathBuf {
  method node_image_bin_dir (line 102) | pub fn node_image_bin_dir(&self, node: &str, npm: &str) -> PathBuf {
  method bin_dir (line 109) | pub fn bin_dir(&self) -> PathBuf {
  method node_image_bin_dir (line 116) | pub fn node_image_bin_dir(&self, node: &str, npm: &str) -> PathBuf {

FILE: crates/volta-layout/src/v1.rs
  method package_distro_file (line 46) | pub fn package_distro_file(&self, name: &str, version: &str) -> PathBuf {
  method package_distro_shasum (line 53) | pub fn package_distro_shasum(&self, name: &str, version: &str) -> PathBuf {
  method node_image_dir (line 60) | pub fn node_image_dir(&self, node: &str, npm: &str) -> PathBuf {
  method yarn_image_dir (line 64) | pub fn yarn_image_dir(&self, version: &str) -> PathBuf {
  method yarn_image_bin_dir (line 68) | pub fn yarn_image_bin_dir(&self, version: &str) -> PathBuf {
  method package_image_dir (line 72) | pub fn package_image_dir(&self, name: &str, version: &str) -> PathBuf {
  method default_package_config_file (line 76) | pub fn default_package_config_file(&self, package_name: &str) -> PathBuf {
  method default_tool_bin_config (line 83) | pub fn default_tool_bin_config(&self, bin_name: &str) -> PathBuf {
  method node_npm_version_file (line 87) | pub fn node_npm_version_file(&self, version: &str) -> PathBuf {
  method shim_file (line 94) | pub fn shim_file(&self, toolname: &str) -> PathBuf {
  method shim_git_bash_script_file (line 101) | pub fn shim_git_bash_script_file(&self, toolname: &str) -> PathBuf {
  method node_image_bin_dir (line 105) | pub fn node_image_bin_dir(&self, node: &str, npm: &str) -> PathBuf {
  method node_image_bin_dir (line 112) | pub fn node_image_bin_dir(&self, node: &str, npm: &str) -> PathBuf {

FILE: crates/volta-layout/src/v2.rs
  method package_distro_file (line 44) | pub fn package_distro_file(&self, name: &str, version: &str) -> PathBuf {
  method package_distro_shasum (line 51) | pub fn package_distro_shasum(&self, name: &str, version: &str) -> PathBuf {
  method node_image_dir (line 58) | pub fn node_image_dir(&self, node: &str) -> PathBuf {
  method npm_image_dir (line 62) | pub fn npm_image_dir(&self, npm: &str) -> PathBuf {
  method npm_image_bin_dir (line 66) | pub fn npm_image_bin_dir(&self, npm: &str) -> PathBuf {
  method yarn_image_dir (line 70) | pub fn yarn_image_dir(&self, version: &str) -> PathBuf {
  method yarn_image_bin_dir (line 74) | pub fn yarn_image_bin_dir(&self, version: &str) -> PathBuf {
  method package_image_dir (line 78) | pub fn package_image_dir(&self, name: &str, version: &str) -> PathBuf {
  method default_package_config_file (line 82) | pub fn default_package_config_file(&self, package_name: &str) -> PathBuf {
  method default_tool_bin_config (line 89) | pub fn default_tool_bin_config(&self, bin_name: &str) -> PathBuf {
  method node_npm_version_file (line 93) | pub fn node_npm_version_file(&self, version: &str) -> PathBuf {
  method shim_file (line 100) | pub fn shim_file(&self, toolname: &str) -> PathBuf {
  method shim_git_bash_script_file (line 107) | pub fn shim_git_bash_script_file(&self, toolname: &str) -> PathBuf {
  method node_image_bin_dir (line 111) | pub fn node_image_bin_dir(&self, node: &str) -> PathBuf {
  method node_image_bin_dir (line 118) | pub fn node_image_bin_dir(&self, node: &str) -> PathBuf {

FILE: crates/volta-layout/src/v3.rs
  method node_image_dir (line 46) | pub fn node_image_dir(&self, node: &str) -> PathBuf {
  method npm_image_dir (line 50) | pub fn npm_image_dir(&self, npm: &str) -> PathBuf {
  method npm_image_bin_dir (line 54) | pub fn npm_image_bin_dir(&self, npm: &str) -> PathBuf {
  method pnpm_image_dir (line 58) | pub fn pnpm_image_dir(&self, version: &str) -> PathBuf {
  method pnpm_image_bin_dir (line 62) | pub fn pnpm_image_bin_dir(&self, version: &str) -> PathBuf {
  method yarn_image_dir (line 66) | pub fn yarn_image_dir(&self, version: &str) -> PathBuf {
  method yarn_image_bin_dir (line 70) | pub fn yarn_image_bin_dir(&self, version: &str) -> PathBuf {
  method package_image_dir (line 74) | pub fn package_image_dir(&self, name: &str) -> PathBuf {
  method default_package_config_file (line 78) | pub fn default_package_config_file(&self, package_name: &str) -> PathBuf {
  method default_tool_bin_config (line 85) | pub fn default_tool_bin_config(&self, bin_name: &str) -> PathBuf {
  method node_npm_version_file (line 89) | pub fn node_npm_version_file(&self, version: &str) -> PathBuf {
  method shim_file (line 96) | pub fn shim_file(&self, toolname: &str) -> PathBuf {
  method shared_lib_dir (line 100) | pub fn shared_lib_dir(&self, library: &str) -> PathBuf {
  method shim_git_bash_script_file (line 107) | pub fn shim_git_bash_script_file(&self, toolname: &str) -> PathBuf {
  method node_image_bin_dir (line 111) | pub fn node_image_bin_dir(&self, node: &str) -> PathBuf {
  method node_image_bin_dir (line 118) | pub fn node_image_bin_dir(&self, node: &str) -> PathBuf {

FILE: crates/volta-layout/src/v4.rs
  method node_image_dir (line 45) | pub fn node_image_dir(&self, node: &str) -> PathBuf {
  method npm_image_dir (line 49) | pub fn npm_image_dir(&self, npm: &str) -> PathBuf {
  method npm_image_bin_dir (line 53) | pub fn npm_image_bin_dir(&self, npm: &str) -> PathBuf {
  method pnpm_image_dir (line 57) | pub fn pnpm_image_dir(&self, version: &str) -> PathBuf {
  method pnpm_image_bin_dir (line 61) | pub fn pnpm_image_bin_dir(&self, version: &str) -> PathBuf {
  method yarn_image_dir (line 65) | pub fn yarn_image_dir(&self, version: &str) -> PathBuf {
  method yarn_image_bin_dir (line 69) | pub fn yarn_image_bin_dir(&self, version: &str) -> PathBuf {
  method package_image_dir (line 73) | pub fn package_image_dir(&self, name: &str) -> PathBuf {
  method default_package_config_file (line 77) | pub fn default_package_config_file(&self, package_name: &str) -> PathBuf {
  method default_tool_bin_config (line 84) | pub fn default_tool_bin_config(&self, bin_name: &str) -> PathBuf {
  method node_npm_version_file (line 88) | pub fn node_npm_version_file(&self, version: &str) -> PathBuf {
  method shim_file (line 95) | pub fn shim_file(&self, toolname: &str) -> PathBuf {
  method shared_lib_dir (line 104) | pub fn shared_lib_dir(&self, library: &str) -> PathBuf {
  method shim_git_bash_script_file (line 111) | pub fn shim_git_bash_script_file(&self, toolname: &str) -> PathBuf {
  method node_image_bin_dir (line 115) | pub fn node_image_bin_dir(&self, node: &str) -> PathBuf {
  method node_image_bin_dir (line 122) | pub fn node_image_bin_dir(&self, node: &str) -> PathBuf {

FILE: crates/volta-migrate/src/empty.rs
  type Empty (line 7) | pub struct Empty {
    method new (line 12) | pub fn new(home: PathBuf) -> Self {

FILE: crates/volta-migrate/src/lib.rs
  type MigrationState (line 38) | enum MigrationState {
    method current (line 87) | fn current() -> Fallible<Self> {
    method detect_legacy_state (line 100) | fn detect_legacy_state(home: &Path) -> Fallible<Self> {
  function run_migration (line 141) | pub fn run_migration() -> Fallible<()> {
  function detect_and_migrate (line 156) | fn detect_and_migrate() -> Fallible<()> {

FILE: crates/volta-migrate/src/v0.rs
  type V0 (line 9) | pub struct V0 {
    method new (line 14) | pub fn new(home: PathBuf) -> Self {

FILE: crates/volta-migrate/src/v1.rs
  type V1 (line 17) | pub struct V1 {
    method new (line 22) | pub fn new(home: PathBuf) -> Self {
    method complete_migration (line 32) | fn complete_migration(home: v1::VoltaHome) -> Fallible<Self> {
    type Error (line 43) | type Error = VoltaError;
    method try_from (line 45) | fn try_from(old: Empty) -> Fallible<V1> {
    type Error (line 58) | type Error = VoltaError;
    method try_from (line 60) | fn try_from(old: V0) -> Fallible<V1> {

FILE: crates/volta-migrate/src/v2.rs
  type V2 (line 20) | pub struct V2 {
    method new (line 25) | pub fn new(home: PathBuf) -> Self {
    method complete_migration (line 35) | fn complete_migration(home: v2::VoltaHome) -> Fallible<Self> {
    type Error (line 46) | type Error = VoltaError;
    method try_from (line 48) | fn try_from(old: Empty) -> Fallible<V2> {
    type Error (line 61) | type Error = VoltaError;
    method try_from (line 63) | fn try_from(old: V1) -> Fallible<V2> {
  function clear_default_npm (line 91) | fn clear_default_npm(platform_file: &Path) -> Fallible<()> {
  function shift_node_images (line 133) | fn shift_node_images(old_home: &v1::VoltaHome, new_home: &v2::VoltaHome)...
  function remove_npm_version_from_node_image_dir (line 158) | fn remove_npm_version_from_node_image_dir(

FILE: crates/volta-migrate/src/v3.rs
  type V3 (line 23) | pub struct V3 {
    method new (line 28) | pub fn new(home: PathBuf) -> Self {
    method complete_migration (line 38) | fn complete_migration(home: v3::VoltaHome) -> Fallible<Self> {
    type Error (line 49) | type Error = VoltaError;
    method try_from (line 51) | fn try_from(old: Empty) -> Fallible<Self> {
    type Error (line 64) | type Error = VoltaError;
    method try_from (line 66) | fn try_from(old: V2) -> Fallible<Self> {
  function migrate_packages (line 92) | fn migrate_packages(old_home: &v2::VoltaHome) -> Fallible<()> {
  function get_installed_packages (line 104) | fn get_installed_packages(old_home: &v2::VoltaHome) -> Vec<LegacyPackage...
  function is_migrated_config (line 140) | fn is_migrated_config(config_path: &Path) -> bool {
  function migrate_single_package (line 155) | fn migrate_single_package(config: LegacyPackageConfig, session: &mut Ses...

FILE: crates/volta-migrate/src/v3/config.rs
  type LegacyPackageConfig (line 9) | pub struct LegacyPackageConfig {
    method from_file (line 33) | pub fn from_file(config_file: &Path) -> Option<Self> {
  type LegacyPlatform (line 18) | pub struct LegacyPlatform {
  type NodeVersion (line 25) | pub struct NodeVersion {
  method from (line 41) | fn from(config_platform: LegacyPlatform) -> Self {

FILE: crates/volta-migrate/src/v4.rs
  type V4 (line 16) | pub struct V4 {
    method new (line 21) | pub fn new(home: PathBuf) -> Self {
    method complete_migration (line 31) | fn complete_migration(home: v4::VoltaHome) -> Fallible<Self> {
    type Error (line 42) | type Error = VoltaError;
    method try_from (line 44) | fn try_from(old: Empty) -> Fallible<V4> {
    type Error (line 57) | type Error = VoltaError;
    method try_from (line 59) | fn try_from(old: V3) -> Fallible<V4> {
  function migrate_shims (line 94) | fn migrate_shims(new_home: &v4::VoltaHome) -> Fallible<()> {
  function migrate_shared_directory (line 123) | fn migrate_shared_directory(new_home: &v4::VoltaHome) -> Fallible<()> {

FILE: src/cli.rs
  type Volta (line 20) | pub(crate) struct Volta {
    method run (line 47) | pub(crate) fn run(self, session: &mut Session) -> Fallible<ExitCode> {
  type Subcommand (line 65) | pub(crate) enum Subcommand {
    method run (line 107) | pub(crate) fn run(self, session: &mut Session) -> Fallible<ExitCode> {
  function styles (line 123) | fn styles() -> styling::Styles {

FILE: src/command/completions.rs
  type Completions (line 16) | pub(crate) struct Completions {
  method run (line 31) | fn run(self, session: &mut Session) -> Fallible<ExitCode> {

FILE: src/command/fetch.rs
  type Fetch (line 8) | pub(crate) struct Fetch {
  method run (line 15) | fn run(self, session: &mut Session) -> Fallible<ExitCode> {

FILE: src/command/install.rs
  type Install (line 8) | pub(crate) struct Install {
  method run (line 15) | fn run(self, session: &mut Session) -> Fallible<ExitCode> {

FILE: src/command/list/human.rs
  function format (line 19) | pub(super) fn format(toolchain: &Toolchain) -> Option<String> {
  function display_active (line 47) | fn display_active(
  function display_all (line 87) | fn display_all(
  function display_node (line 110) | fn display_node(runtimes: &[Node]) -> String {
  function display_npms (line 122) | fn display_npms(managers: &[PackageManager]) -> String {
  function display_package_managers (line 142) | fn display_package_managers(kind: PackageManagerKind, managers: &[Packag...
  function display_packages (line 176) | fn display_packages(packages: &[Package]) -> String {
  function display_tool (line 194) | fn display_tool(tool: &str, host_packages: &[Package]) -> String {
  function format_tool_list (line 216) | fn format_tool_list(packages: &[Package]) -> String {
  function format_tool (line 224) | fn format_tool(package: &Package) -> String {
  function format_runtime_list (line 238) | fn format_runtime_list(runtimes: &[Node]) -> String {
  function format_runtime (line 249) | fn format_runtime(runtime: &Node) -> String {
  function format_package_manager_list_condensed (line 254) | fn format_package_manager_list_condensed(package_managers: &[PackageMana...
  function format_package_manager_list_verbose (line 271) | fn format_package_manager_list_verbose(package_managers: &[PackageManage...
  function format_package_manager (line 297) | fn format_package_manager(package_manager: &PackageManager) -> String {
  function format_package_manager_kind (line 304) | fn format_package_manager_kind(kind: PackageManagerKind) -> String {
  function format_package_list (line 313) | fn format_package_list(packages: &[Package]) -> String {
  function format_package (line 324) | fn format_package(package: &Package) -> String {
  function list_package_source (line 370) | fn list_package_source(package: &Package) -> String {
  function wrap (line 379) | fn wrap<S>(text: S) -> String
  function no_runtimes (line 420) | fn no_runtimes() {
  function runtime_only_default (line 431) | fn runtime_only_default() {
  function runtime_only_project (line 453) | fn runtime_only_project() {
  function runtime_and_npm_default (line 475) | fn runtime_and_npm_default() {
  function runtime_and_yarn_default (line 502) | fn runtime_and_yarn_default() {
  function runtime_and_npm_mixed (line 529) | fn runtime_and_npm_mixed() {
  function runtime_and_yarn_mixed (line 556) | fn runtime_and_yarn_mixed() {
  function runtime_and_npm_project (line 583) | fn runtime_and_npm_project() {
  function runtime_and_yarn_project (line 610) | fn runtime_and_yarn_project() {
  function runtime_npm_and_yarn_default (line 637) | fn runtime_npm_and_yarn_default() {
  function runtime_npm_and_yarn_project (line 672) | fn runtime_npm_and_yarn_project() {
  function runtime_npm_and_yarn_mixed (line 707) | fn runtime_npm_and_yarn_mixed() {
  function with_default_tools (line 742) | fn with_default_tools() {
  function with_project_tools (line 796) | fn with_project_tools() {
  function no_runtimes (line 853) | fn no_runtimes() {
  function single_default (line 861) | fn single_default() {
  function single_project (line 874) | fn single_project() {
  function single_installed (line 888) | fn single_installed() {
  function multi (line 902) | fn multi() {
  function none_installed_npm (line 933) | fn none_installed_npm() {
  function none_installed_yarn (line 947) | fn none_installed_yarn() {
  function single_default_npm (line 960) | fn single_default_npm() {
  function single_default_yarn (line 978) | fn single_default_yarn() {
  function single_project_npm (line 996) | fn single_project_npm() {
  function single_project_yarn (line 1014) | fn single_project_yarn() {
  function single_installed_npm (line 1032) | fn single_installed_npm() {
  function single_installed_yarn (line 1050) | fn single_installed_yarn() {
  function multi_npm (line 1068) | fn multi_npm() {
  function multi_yarn (line 1100) | fn multi_yarn() {
  function none (line 1138) | fn none() {
  function single_default (line 1148) | fn single_default() {
  function single_project (line 1170) | fn single_project() {
  function single_fetched (line 1186) | fn single_fetched() {
  function multi_fetched (line 1202) | fn multi_fetched() {
  function multi (line 1227) | fn multi() {
  function none (line 1264) | fn none() {
  function single_default (line 1274) | fn single_default() {
  function single_project (line 1296) | fn single_project() {
  function single_fetched (line 1312) | fn single_fetched() {
  function multi_fetched (line 1328) | fn multi_fetched() {
  function multi (line 1353) | fn multi() {
  function empty (line 1389) | fn empty() {
  function runtime_and_npm (line 1401) | fn runtime_and_npm() {
  function runtime_and_yarn (line 1459) | fn runtime_and_yarn() {
  function full (line 1517) | fn full() {

FILE: src/command/list/mod.rs
  type Format (line 19) | enum Format {
  type Source (line 30) | enum Source {
    method allowed_with (line 43) | fn allowed_with(&self, filter: &Filter) -> bool {
    method fmt (line 53) | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
  type PackageDetails (line 68) | struct PackageDetails {
  type Package (line 75) | enum Package {
    method new (line 93) | fn new(config: &PackageConfig, source: &Source) -> Package {
    method from_inventory_and_project (line 114) | fn from_inventory_and_project(project: Option<&Project>) -> Fallible<V...
    method source (line 126) | fn source(name: &str, project: Option<&Project>) -> Source {
  type Node (line 137) | struct Node {
  type PackageManagerKind (line 143) | enum PackageManagerKind {
    method fmt (line 150) | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
  type PackageManager (line 164) | struct PackageManager {
  type Filter (line 171) | enum Filter {
  type List (line 189) | pub(crate) struct List {
    method output_format (line 250) | fn output_format(&self) -> Format {
  type Subcommand (line 214) | enum Subcommand {
  type Err (line 235) | type Err = std::convert::Infallible;
  method from_str (line 237) | fn from_str(s: &str) -> Result<Self, Self::Err> {
  method run (line 264) | fn run(self, session: &mut Session) -> Fallible<ExitCode> {

FILE: src/command/list/plain.rs
  function format (line 9) | pub(super) fn format(toolchain: &Toolchain) -> Option<String> {
  function describe_runtimes (line 60) | fn describe_runtimes(runtimes: &[Node]) -> Option<String> {
  function describe_package_managers (line 74) | fn describe_package_managers(package_managers: &[PackageManager]) -> Opt...
  function describe_packages (line 88) | fn describe_packages(packages: &[Package]) -> Option<String> {
  function describe_tool_set (line 102) | fn describe_tool_set(name: &str, hosts: &[Package]) -> String {
  function display_node (line 110) | fn display_node(source: &Source, version: &Version) -> String {
  function display_package_manager (line 114) | fn display_package_manager(package_manager: &PackageManager) -> String {
  function package_source (line 122) | fn package_source(package: &Package) -> String {
  function display_package (line 130) | fn display_package(package: &Package) -> String {
  function display_tool (line 176) | fn display_tool(name: &str, host: &Package) -> Option<String> {
  function default (line 222) | fn default() {
  function project (line 231) | fn project() {
  function installed_not_set (line 240) | fn installed_not_set() {
  function default (line 255) | fn default() {
  function project (line 268) | fn project() {
  function installed_not_set (line 281) | fn installed_not_set() {
  function default (line 300) | fn default() {
  function project (line 313) | fn project() {
  function installed_not_set (line 326) | fn installed_not_set() {
  function single_default (line 344) | fn single_default() {
  function single_project (line 361) | fn single_project() {
  function mixed (line 375) | fn mixed() {
  function installed_not_set (line 405) | fn installed_not_set() {
  function default (line 423) | fn default() {
  function project (line 443) | fn project() {
  function fetched (line 460) | fn fetched() {
  function full (line 480) | fn full() {

FILE: src/command/list/toolchain.rs
  type Toolchain (line 12) | pub(super) enum Toolchain {
    method active (line 124) | pub(super) fn active(
    method all (line 166) | pub(super) fn all(
    method node (line 206) | pub(super) fn node(
    method npm (line 227) | pub(super) fn npm(
    method pnpm (line 254) | pub(super) fn pnpm(
    method yarn (line 281) | pub(super) fn yarn(
    method package_or_tool (line 308) | pub(super) fn package_or_tool(
  type Lookup (line 36) | enum Lookup {
    method version_from_spec (line 48) | fn version_from_spec(&self) -> impl Fn(&PlatformSpec) -> Option<Versio...
    method version_source (line 57) | fn version_source(
    method active_tool (line 90) | fn active_tool(
  function tool_source (line 110) | fn tool_source(name: &str, project: Option<&Project>) -> Fallible<Source> {

FILE: src/command/mod.rs
  type Command (line 27) | pub(crate) trait Command: Sized {
    method run (line 31) | fn run(self, session: &mut Session) -> Fallible<ExitCode>;

FILE: src/command/pin.rs
  type Pin (line 8) | pub(crate) struct Pin {
  method run (line 15) | fn run(self, session: &mut Session) -> Fallible<ExitCode> {

FILE: src/command/run.rs
  type Run (line 14) | pub(crate) struct Run {
    method parse_platform (line 93) | fn parse_platform(&self, session: &mut Session) -> Fallible<CliPlatfor...
    method parse_envs (line 137) | fn parse_envs(&self) -> HashMap<&str, &str> {
  method run (line 58) | fn run(self, session: &mut Session) -> Fallible<ExitCode> {

FILE: src/command/setup.rs
  type Setup (line 11) | pub(crate) struct Setup {}
  method run (line 14) | fn run(self, session: &mut Session) -> Fallible<ExitCode> {
  function setup_environment (line 41) | pub fn setup_environment() -> Fallible<()> {
  function determine_profiles (line 96) | fn determine_profiles() -> Fallible<Vec<PathBuf>> {
  function add_zsh_profile (line 117) | fn add_zsh_profile(home_dir: &Path, shell: &str, profiles: &mut Vec<Path...
  function add_bash_profiles (line 140) | fn add_bash_profiles(home_dir: &Path, shell: &str, profiles: &mut Vec<Pa...
  function add_fish_profile (line 171) | fn add_fish_profile(home_dir: &Path, shell: &str, profiles: &mut Vec<Pat...
  function read_profile_without_volta (line 179) | fn read_profile_without_volta(path: &Path) -> Option<String> {
  function format_home (line 195) | fn format_home(volta_home: &Path) -> String {
  function write_profile_sh (line 207) | fn write_profile_sh(path: &Path, contents: String, volta_home: &str) -> ...
  function write_profile_fish (line 216) | fn write_profile_fish(path: &Path, contents: String, volta_home: &str) -...
  function setup_environment (line 236) | pub fn setup_environment() -> Fallible<()> {

FILE: src/command/uninstall.rs
  type Uninstall (line 9) | pub(crate) struct Uninstall {
  method run (line 15) | fn run(self, session: &mut Session) -> Fallible<ExitCode> {

FILE: src/command/use.rs
  constant USAGE (line 8) | pub(crate) const USAGE: &str = "The subcommand `use` is deprecated.
  constant ADVICE (line 14) | const ADVICE: &str = "
  type Use (line 20) | pub(crate) struct Use {
  method run (line 26) | fn run(self, session: &mut Session) -> Fallible<ExitCode> {

FILE: src/command/which.rs
  type Which (line 14) | pub(crate) struct Which {
  method run (line 24) | fn run(self, session: &mut Session) -> Fallible<ExitCode> {

FILE: src/common.rs
  type Error (line 6) | pub enum Error {
  function ensure_layout (line 11) | pub fn ensure_layout() -> Result<(), Error> {
  type IntoResult (line 26) | pub trait IntoResult<T> {
    method into_result (line 27) | fn into_result(self) -> Result<T, Error>;
  function into_result (line 31) | fn into_result(self) -> Result<(), Error> {

FILE: src/main.rs
  function main (line 15) | pub fn main() {

FILE: src/volta-migrate.rs
  function main (line 6) | pub fn main() {

FILE: src/volta-shim.rs
  function main (line 10) | pub fn main() {

FILE: tests/acceptance/corrupted_download.rs
  constant NODE_VERSION_INFO (line 9) | const NODE_VERSION_INFO: &str = r#"[
  constant NODE_VERSION_FIXTURES (line 15) | const NODE_VERSION_FIXTURES: [DistroMetadata; 2] = [
  constant PNPM_VERSION_INFO (line 28) | const PNPM_VERSION_INFO: &str = r#"
  constant PNPM_VERSION_FIXTURES (line 39) | const PNPM_VERSION_FIXTURES: [DistroMetadata; 2] = [
  constant YARN_1_VERSION_INFO (line 52) | const YARN_1_VERSION_INFO: &str = r#"{
  constant YARN_1_VERSION_FIXTURES (line 61) | const YARN_1_VERSION_FIXTURES: [DistroMetadata; 2] = [
  function install_corrupted_node_leaves_inventory_unchanged (line 75) | fn install_corrupted_node_leaves_inventory_unchanged() {
  function install_valid_node_saves_to_inventory (line 90) | fn install_valid_node_saves_to_inventory() {
  function install_corrupted_pnpm_leaves_inventory_unchanged (line 105) | fn install_corrupted_pnpm_leaves_inventory_unchanged() {
  function install_valid_pnpm_saves_to_inventory (line 123) | fn install_valid_pnpm_saves_to_inventory() {
  function install_corrupted_yarn_leaves_inventory_unchanged (line 142) | fn install_corrupted_yarn_leaves_inventory_unchanged() {
  function install_valid_yarn_saves_to_inventory (line 159) | fn install_valid_yarn_saves_to_inventory() {

FILE: tests/acceptance/direct_install.rs
  function platform_with_node (line 8) | fn platform_with_node(node: &str) -> String {
  function platform_with_node_yarn (line 21) | fn platform_with_node_yarn(node: &str, yarn: &str) -> String {
  constant NODE_VERSION_INFO (line 34) | const NODE_VERSION_INFO: &str = r#"[
  constant YARN_1_VERSION_INFO (line 117) | const YARN_1_VERSION_INFO: &str = r#"[
  constant YARN_1_VERSION_FIXTURES (line 125) | const YARN_1_VERSION_FIXTURES: [DistroMetadata; 4] = [
  constant NPM_VERSION_INFO (line 148) | const NPM_VERSION_INFO: &str = r#"
  constant NPM_VERSION_FIXTURES (line 160) | const NPM_VERSION_FIXTURES: [DistroMetadata; 3] = [
  function npm_global_install_node_intercepts (line 179) | fn npm_global_install_node_intercepts() {
  function yarn_global_add_node_intercepts (line 197) | fn yarn_global_add_node_intercepts() {
  function npm_global_install_npm_intercepts (line 215) | fn npm_global_install_npm_intercepts() {
  function yarn_global_add_npm_intercepts (line 235) | fn yarn_global_add_npm_intercepts() {
  function npm_global_install_yarn_intercepts (line 255) | fn npm_global_install_yarn_intercepts() {
  function yarn_global_add_yarn_intercepts (line 275) | fn yarn_global_add_yarn_intercepts() {
  function npm_global_install_supports_multiples (line 295) | fn npm_global_install_supports_multiples() {
  function npm_global_install_without_packages_is_treated_as_not_global (line 320) | fn npm_global_install_without_packages_is_treated_as_not_global() {
  function yarn_global_add_supports_multiples (line 337) | fn yarn_global_add_supports_multiples() {
  function yarn_global_add_without_packages_is_treated_as_not_global (line 362) | fn yarn_global_add_without_packages_is_treated_as_not_global() {
  function npm_global_with_override_does_not_intercept (line 381) | fn npm_global_with_override_does_not_intercept() {
  function yarn_global_with_override_does_not_intercept (line 398) | fn yarn_global_with_override_does_not_intercept() {

FILE: tests/acceptance/direct_uninstall.rs
  function platform_with_node (line 10) | fn platform_with_node(node: &str) -> String {
  function platform_with_node_yarn (line 23) | fn platform_with_node_yarn(node: &str, yarn: &str) -> String {
  constant PKG_CONFIG_COWSAY (line 36) | const PKG_CONFIG_COWSAY: &str = r#"{
  constant PKG_CONFIG_TYPESCRIPT (line 51) | const PKG_CONFIG_TYPESCRIPT: &str = r#"{
  function bin_config (line 66) | fn bin_config(name: &str, pkg: &str) -> String {
  constant YARN_1_VERSION_FIXTURES (line 113) | const YARN_1_VERSION_FIXTURES: [DistroMetadata; 1] = [DistroMetadata {
  function npm_uninstall_uses_volta_logic (line 120) | fn npm_uninstall_uses_volta_logic() {
  function npm_uninstall_supports_multiples (line 152) | fn npm_uninstall_supports_multiples() {
  function npm_uninstall_without_packages_skips_volta_logic (line 201) | fn npm_uninstall_without_packages_skips_volta_logic() {
  function yarn_remove_uses_volta_logic (line 217) | fn yarn_remove_uses_volta_logic() {
  function yarn_remove_supports_multiples (line 249) | fn yarn_remove_supports_multiples() {
  function yarn_remove_without_packages_skips_volta_logic (line 298) | fn yarn_remove_without_packages_skips_volta_logic() {

FILE: tests/acceptance/execute_binary.rs
  constant PKG_CONFIG_BASIC (line 9) | const PKG_CONFIG_BASIC: &str = r#"{
  function node_bin (line 24) | fn node_bin(version: &str) -> String {
  function npm_bin (line 46) | fn npm_bin(version: &str) -> String {
  function pnpm_bin (line 68) | fn pnpm_bin(version: &str) -> String {
  function yarn_bin (line 90) | fn yarn_bin(version: &str) -> String {
  function cowsay_bin (line 112) | fn cowsay_bin(name: &str, version: &str) -> String {
  function cowsay_bin_info (line 134) | fn cowsay_bin_info(version: &str) -> Vec<PackageBinInfo> {
  function bin_config (line 147) | fn bin_config(name: &str) -> String {
  constant PACKAGE_JSON_NPM_NO_DEP (line 164) | const PACKAGE_JSON_NPM_NO_DEP: &str = r#"{
  constant PACKAGE_JSON_NPM_WITH_DEP (line 171) | const PACKAGE_JSON_NPM_WITH_DEP: &str = r#"{
  constant PACKAGE_JSON_YARN_PNP_WITH_DEP (line 181) | const PACKAGE_JSON_YARN_PNP_WITH_DEP: &str = r#"{
  constant PLATFORM_NODE_NPM (line 192) | const PLATFORM_NODE_NPM: &str = r#"{
  function default_binary_no_project (line 200) | fn default_binary_no_project() {
  function default_binary_no_project_dep (line 236) | fn default_binary_no_project_dep() {
  function project_local_binary (line 272) | fn project_local_binary() {
  function project_local_binary_pnp (line 311) | fn project_local_binary_pnp() {

FILE: tests/acceptance/hooks.rs
  constant WORKSPACE_PACKAGE_JSON (line 14) | const WORKSPACE_PACKAGE_JSON: &str = r#"
  constant PROJECT_PACKAGE_JSON (line 21) | const PROJECT_PACKAGE_JSON: &str = r#"
  function default_hooks_json (line 60) | fn default_hooks_json() -> String {
  function project_hooks_json (line 90) | fn project_hooks_json() -> String {
  function workspace_hooks_json (line 104) | fn workspace_hooks_json() -> String {
  function pnpm_hooks_json (line 123) | fn pnpm_hooks_json() -> String {
  function yarn_hooks_json (line 140) | fn yarn_hooks_json() -> String {
  function yarn_hooks_format_json (line 157) | fn yarn_hooks_format_json(format: &str) -> String {
  function redirects_download (line 177) | fn redirects_download() {
  function merges_project_and_default_hooks (line 209) | fn merges_project_and_default_hooks() {
  function merges_workspace_hooks (line 267) | fn merges_workspace_hooks() {
  function pnpm_latest_with_hook_reads_index (line 341) | fn pnpm_latest_with_hook_reads_index() {
  function pnpm_no_version_with_hook_reads_index (line 376) | fn pnpm_no_version_with_hook_reads_index() {
  function yarn_latest_with_hook_reads_latest (line 411) | fn yarn_latest_with_hook_reads_latest() {
  function yarn_no_version_with_hook_reads_latest (line 432) | fn yarn_no_version_with_hook_reads_latest() {
  function yarn_semver_with_hook_uses_old_format (line 453) | fn yarn_semver_with_hook_uses_old_format() {
  function yarn_semver_with_hook_uses_configured_format (line 483) | fn yarn_semver_with_hook_uses_configured_format() {

FILE: tests/acceptance/merged_platform.rs
  constant PACKAGE_JSON_NODE_ONLY (line 13) | const PACKAGE_JSON_NODE_ONLY: &str = r#"{
  constant PACKAGE_JSON_WITH_NPM (line 20) | const PACKAGE_JSON_WITH_NPM: &str = r#"{
  constant PACKAGE_JSON_WITH_PNPM (line 28) | const PACKAGE_JSON_WITH_PNPM: &str = r#"{
  constant PACKAGE_JSON_WITH_YARN (line 36) | const PACKAGE_JSON_WITH_YARN: &str = r#"{
  constant PLATFORM_NODE_ONLY (line 44) | const PLATFORM_NODE_ONLY: &str = r#"{
  constant PLATFORM_WITH_NPM (line 51) | const PLATFORM_WITH_NPM: &str = r#"{
  constant PLATFORM_WITH_PNPM (line 58) | const PLATFORM_WITH_PNPM: &str = r#"{
  constant PLATFORM_WITH_YARN (line 66) | const PLATFORM_WITH_YARN: &str = r#"{
  function events_hooks_json (line 100) | fn events_hooks_json() -> String {
  constant NPM_VERSION_FIXTURES (line 159) | const NPM_VERSION_FIXTURES: [DistroMetadata; 2] = [
  constant PNPM_VERSION_FIXTURES (line 172) | const PNPM_VERSION_FIXTURES: [DistroMetadata; 2] = [
  constant YARN_1_VERSION_FIXTURES (line 185) | const YARN_1_VERSION_FIXTURES: [DistroMetadata; 2] = [
  function uses_project_npm_if_available (line 199) | fn uses_project_npm_if_available() {
  function uses_bundled_npm_in_project_without_npm (line 218) | fn uses_bundled_npm_in_project_without_npm() {
  function uses_default_npm_outside_project (line 237) | fn uses_default_npm_outside_project() {
  function uses_bundled_npm_outside_project (line 255) | fn uses_bundled_npm_outside_project() {
  function uses_project_yarn_if_available (line 273) | fn uses_project_yarn_if_available() {
  function uses_default_yarn_in_project_without_yarn (line 310) | fn uses_default_yarn_in_project_without_yarn() {
  function uses_default_yarn_outside_project (line 330) | fn uses_default_yarn_outside_project() {
  function throws_project_error_in_project (line 349) | fn throws_project_error_in_project() {
  function throws_default_error_outside_project (line 364) | fn throws_default_error_outside_project() {
  function uses_project_pnpm_if_available (line 376) | fn uses_project_pnpm_if_available() {
  function uses_default_pnpm_in_project_without_pnpm (line 414) | fn uses_default_pnpm_in_project_without_pnpm() {
  function uses_default_pnpm_outside_project (line 435) | fn uses_default_pnpm_outside_project() {
  function uses_pnpm_throws_project_error_in_project (line 455) | fn uses_pnpm_throws_project_error_in_project() {

FILE: tests/acceptance/migrations.rs
  function empty_volta_home_is_created (line 7) | fn empty_volta_home_is_created() {
  function legacy_v0_volta_home_is_upgraded (line 47) | fn legacy_v0_volta_home_is_upgraded() {
  function tagged_v1_volta_home_is_upgraded (line 92) | fn tagged_v1_volta_home_is_upgraded() {
  function tagged_v1_to_v2_keeps_custom_npm (line 161) | fn tagged_v1_to_v2_keeps_custom_npm() {
  function tagged_v1_to_v2_keeps_migrated_node_images (line 187) | fn tagged_v1_to_v2_keeps_migrated_node_images() {
  function current_v4_volta_home_is_unchanged (line 212) | fn current_v4_volta_home_is_unchanged() {

FILE: tests/acceptance/run_shim_directly.rs
  function shows_pretty_error_when_calling_shim_directly (line 9) | fn shows_pretty_error_when_calling_shim_directly() {

FILE: tests/acceptance/support/events_helpers.rs
  type EventKindMatcher (line 9) | pub enum EventKindMatcher<'a> {
  function match_start (line 17) | pub fn match_start() -> EventKindMatcher<'static> {
  function match_error (line 21) | pub fn match_error(exit_code: i32, error: &str) -> EventKindMatcher {
  function match_end (line 25) | pub fn match_end(exit_code: i32) -> EventKindMatcher<'static> {
  function match_tool_end (line 29) | pub fn match_tool_end(exit_code: i32) -> EventKindMatcher<'static> {
  function match_args (line 33) | pub fn match_args(argv: &str) -> EventKindMatcher {
  function assert_events (line 37) | pub fn assert_events(sandbox: &Sandbox, matchers: Vec<(&str, EventKindMa...

FILE: tests/acceptance/support/sandbox.rs
  type CacheBuilder (line 18) | struct CacheBuilder {
    method new (line 27) | pub fn new(path: PathBuf, expiry_path: PathBuf, contents: &str, expire...
    method build (line 36) | fn build(&self) {
    method dirname (line 69) | fn dirname(&self) -> &Path {
  type EnvVar (line 75) | pub struct EnvVar {
    method new (line 81) | pub fn new(name: &str, value: &str) -> Self {
  type FileBuilder (line 91) | pub struct FileBuilder {
    method new (line 98) | pub fn new(path: PathBuf, contents: &str) -> FileBuilder {
    method make_executable (line 106) | pub fn make_executable(mut self) -> Self {
    method build (line 111) | pub fn build(&self) {
    method dirname (line 123) | fn dirname(&self) -> &Path {
  type ShimBuilder (line 128) | struct ShimBuilder {
    method new (line 133) | fn new(name: String) -> ShimBuilder {
    method build (line 137) | fn build(&self) {
  type PackageBinInfo (line 143) | pub struct PackageBinInfo {
  type SandboxBuilder (line 149) | pub struct SandboxBuilder {
    method root (line 300) | pub fn root(&self) -> PathBuf {
    method new (line 304) | pub fn new(root: PathBuf) -> SandboxBuilder {
    method node_cache (line 327) | pub fn node_cache(mut self, cache: &str, expired: bool) -> Self {
    method package_json (line 338) | pub fn package_json(mut self, contents: &str) -> Self {
    method platform (line 345) | pub fn platform(mut self, contents: &str) -> Self {
    method default_hooks (line 352) | pub fn default_hooks(mut self, contents: &str) -> Self {
    method layout_file (line 359) | pub fn layout_file(mut self, version: &str) -> Self {
    method env (line 364) | pub fn env(mut self, name: &str, value: &str) -> Self {
    method node_available_versions (line 370) | pub fn node_available_versions(mut self, body: &str) -> Self {
    method yarn_1_available_versions (line 382) | pub fn yarn_1_available_versions(mut self, body: &str) -> Self {
    method yarn_berry_available_versions (line 393) | pub fn yarn_berry_available_versions(mut self, body: &str) -> Self {
    method npm_available_versions (line 404) | pub fn npm_available_versions(mut self, body: &str) -> Self {
    method pnpm_available_versions (line 416) | pub fn pnpm_available_versions(mut self, body: &str) -> Self {
    method mock_not_found (line 430) | pub fn mock_not_found(mut self) -> Self {
    method distro_mock (line 436) | fn distro_mock<T: DistroFixture>(mut self, fx: &T) -> Self {
    method distro_mocks (line 470) | pub fn distro_mocks<T: DistroFixture>(self, fixtures: &[DistroMetadata...
    method file (line 479) | pub fn file(mut self, path: &str, contents: &str) -> Self {
    method project_file (line 486) | pub fn project_file(mut self, path: &str, contents: &str) -> Self {
    method executable_file (line 496) | pub fn executable_file(mut self, path: &str, contents: &str) -> Self {
    method prepend_exec_dir_to_path (line 509) | pub fn prepend_exec_dir_to_path(mut self) -> Self {
    method package_config (line 521) | pub fn package_config(mut self, name: &str, contents: &str) -> Self {
    method binary_config (line 529) | pub fn binary_config(mut self, name: &str, contents: &str) -> Self {
    method shim (line 536) | pub fn shim(mut self, name: &str) -> Self {
    method package_image (line 542) | pub fn package_image(
    method project_bins (line 571) | pub fn project_bins(mut self, bins: Vec<PackageBinInfo>) -> Self {
    method project_pnp (line 590) | pub fn project_pnp(mut self) -> Self {
    method setup_node_binary (line 597) | pub fn setup_node_binary(
    method setup_npm_binary (line 617) | pub fn setup_npm_binary(mut self, version: &str, contents: &str) -> Se...
    method setup_pnpm_binary (line 632) | pub fn setup_pnpm_binary(mut self, version: &str, contents: &str) -> S...
    method setup_yarn_binary (line 647) | pub fn setup_yarn_binary(mut self, version: &str, contents: &str) -> S...
    method node_npm_version_file (line 662) | pub fn node_npm_version_file(mut self, node_version: &str, npm_version...
    method add_dir_to_path (line 669) | pub fn add_dir_to_path(mut self, dir: PathBuf) -> Self {
    method add_exec_dir_to_path (line 675) | pub fn add_exec_dir_to_path(mut self) -> Self {
    method build (line 685) | pub fn build(mut self) -> Sandbox {
    method rm_root (line 723) | fn rm_root(&self) {
  type DistroFixture (line 158) | pub trait DistroFixture: From<DistroMetadata> {
    method server_path (line 159) | fn server_path(&self) -> String;
    method fixture_path (line 160) | fn fixture_path(&self) -> String;
    method metadata (line 161) | fn metadata(&self) -> &DistroMetadata;
    method server_path (line 222) | fn server_path(&self) -> String {
    method fixture_path (line 228) | fn fixture_path(&self) -> String {
    method metadata (line 234) | fn metadata(&self) -> &DistroMetadata {
    method server_path (line 240) | fn server_path(&self) -> String {
    method fixture_path (line 244) | fn fixture_path(&self) -> String {
    method metadata (line 248) | fn metadata(&self) -> &DistroMetadata {
    method server_path (line 254) | fn server_path(&self) -> String {
    method fixture_path (line 258) | fn fixture_path(&self) -> String {
    method metadata (line 262) | fn metadata(&self) -> &DistroMetadata {
    method server_path (line 268) | fn server_path(&self) -> String {
    method fixture_path (line 272) | fn fixture_path(&self) -> String {
    method metadata (line 276) | fn metadata(&self) -> &DistroMetadata {
    method server_path (line 282) | fn server_path(&self) -> String {
    method fixture_path (line 289) | fn fixture_path(&self) -> String {
    method metadata (line 293) | fn metadata(&self) -> &DistroMetadata {
  type DistroMetadata (line 165) | pub struct DistroMetadata {
  type NodeFixture (line 171) | pub struct NodeFixture {
    method from (line 192) | fn from(metadata: DistroMetadata) -> Self {
  type NpmFixture (line 175) | pub struct NpmFixture {
    method from (line 198) | fn from(metadata: DistroMetadata) -> Self {
  type PnpmFixture (line 179) | pub struct PnpmFixture {
    method from (line 204) | fn from(metadata: DistroMetadata) -> Self {
  type Yarn1Fixture (line 183) | pub struct Yarn1Fixture {
    method from (line 210) | fn from(metadata: DistroMetadata) -> Self {
  type YarnBerryFixture (line 187) | pub struct YarnBerryFixture {
    method from (line 216) | fn from(metadata: DistroMetadata) -> Self {
  function home_dir (line 730) | fn home_dir() -> PathBuf {
  function volta_home (line 733) | fn volta_home() -> PathBuf {
  function volta_tmp_dir (line 736) | fn volta_tmp_dir() -> PathBuf {
  function volta_bin_dir (line 739) | fn volta_bin_dir() -> PathBuf {
  function volta_log_dir (line 742) | fn volta_log_dir() -> PathBuf {
  function volta_postscript (line 745) | fn volta_postscript() -> PathBuf {
  function volta_tools_dir (line 748) | fn volta_tools_dir() -> PathBuf {
  function inventory_dir (line 751) | fn inventory_dir() -> PathBuf {
  function user_dir (line 754) | fn user_dir() -> PathBuf {
  function image_dir (line 757) | fn image_dir() -> PathBuf {
  function node_inventory_dir (line 760) | fn node_inventory_dir() -> PathBuf {
  function pnpm_inventory_dir (line 763) | fn pnpm_inventory_dir() -> PathBuf {
  function yarn_inventory_dir (line 766) | fn yarn_inventory_dir() -> PathBuf {
  function package_inventory_dir (line 769) | fn package_inventory_dir() -> PathBuf {
  function cache_dir (line 772) | fn cache_dir() -> PathBuf {
  function node_cache_dir (line 775) | fn node_cache_dir() -> PathBuf {
  function node_index_file (line 779) | fn node_index_file() -> PathBuf {
  function node_index_expiry_file (line 783) | fn node_index_expiry_file() -> PathBuf {
  function package_json_file (line 786) | fn package_json_file(mut root: PathBuf) -> PathBuf {
  function package_config_file (line 790) | fn package_config_file(name: &str) -> PathBuf {
  function binary_config_file (line 793) | fn binary_config_file(name: &str) -> PathBuf {
  function shim_file (line 796) | fn shim_file(name: &str) -> PathBuf {
  function package_image_dir (line 799) | fn package_image_dir(name: &str) -> PathBuf {
  function node_image_dir (line 802) | fn node_image_dir(version: &str) -> PathBuf {
  function npm_image_dir (line 805) | fn npm_image_dir(version: &str) -> PathBuf {
  function pnpm_image_dir (line 808) | fn pnpm_image_dir(version: &str) -> PathBuf {
  function yarn_image_dir (line 811) | fn yarn_image_dir(version: &str) -> PathBuf {
  function default_platform_file (line 814) | fn default_platform_file() -> PathBuf {
  function default_hooks_file (line 817) | fn default_hooks_file() -> PathBuf {
  function layout_file (line 820) | fn layout_file(version: &str) -> PathBuf {
  function node_npm_version_file (line 823) | fn node_npm_version_file(node_version: &str) -> PathBuf {
  function sandbox_path (line 827) | fn sandbox_path(path: &str) -> PathBuf {
  type Sandbox (line 831) | pub struct Sandbox {
    method root (line 841) | pub fn root(&self) -> PathBuf {
    method process (line 851) | pub fn process<T: AsRef<OsStr>>(&self, program: T) -> ProcessBuilder {
    method volta (line 878) | pub fn volta(&self, cmd: &str) -> ProcessBuilder {
    method npm (line 888) | pub fn npm(&self, cmd: &str) -> ProcessBuilder {
    method pnpm (line 896) | pub fn pnpm(&self, cmd: &str) -> ProcessBuilder {
    method yarn (line 904) | pub fn yarn(&self, cmd: &str) -> ProcessBuilder {
    method exec_shim (line 912) | pub fn exec_shim(&self, bin: &str, cmd: &str) -> ProcessBuilder {
    method read_package_json (line 918) | pub fn read_package_json(&self) -> String {
    method read_log_dir (line 923) | pub fn read_log_dir(&self) -> Option<fs::ReadDir> {
    method remove_volta_home (line 927) | pub fn remove_volta_home(&self) {
    method node_inventory_archive_exists (line 933) | pub fn node_inventory_archive_exists(&self, version: &Version) -> bool {
    method pnpm_inventory_archive_exists (line 939) | pub fn pnpm_inventory_archive_exists(&self, version: &str) -> bool {
    method yarn_inventory_archive_exists (line 945) | pub fn yarn_inventory_archive_exists(&self, version: &str) -> bool {
    method package_config_exists (line 951) | pub fn package_config_exists(name: &str) -> bool {
    method bin_config_exists (line 954) | pub fn bin_config_exists(name: &str) -> bool {
    method shim_exists (line 957) | pub fn shim_exists(name: &str) -> bool {
    method path_exists (line 960) | pub fn path_exists(path: &str) -> bool {
    method package_image_exists (line 963) | pub fn package_image_exists(name: &str) -> bool {
    method read_default_platform (line 967) | pub fn read_default_platform() -> String {
  method drop (line 973) | fn drop(&mut self) {
  function sandbox (line 979) | pub fn sandbox() -> SandboxBuilder {
  function cargo_dir (line 984) | pub fn cargo_dir() -> PathBuf {
  function volta_exe (line 999) | fn volta_exe() -> PathBuf {
  function shim_exe (line 1003) | pub fn shim_exe() -> PathBuf {
  function split_and_add_args (line 1007) | fn split_and_add_args(p: &mut ProcessBuilder, s: &str) {
  function read_file_to_string (line 1016) | fn read_file_to_string(file_path: PathBuf) -> String {

FILE: tests/acceptance/verbose_errors.rs
  constant NODE_VERSION_INFO (line 9) | const NODE_VERSION_INFO: &str = r#"[
  function no_cause_shown_if_no_verbose_flag (line 18) | fn no_cause_shown_if_no_verbose_flag() {
  function cause_shown_if_verbose_flag (line 33) | fn cause_shown_if_verbose_flag() {
  function no_cause_if_no_underlying_error (line 48) | fn no_cause_if_no_underlying_error() {
  function error_log_if_underlying_cause (line 60) | fn error_log_if_underlying_cause() {
  function no_error_log_if_no_underlying_cause (line 78) | fn no_error_log_if_no_underlying_cause() {
  function cause_shown_in_ci (line 95) | fn cause_shown_in_ci() {
  function no_error_log_in_ci (line 116) | fn no_error_log_in_ci() {

FILE: tests/acceptance/volta_bypass.rs
  function shim_skips_platform_checks_on_bypass (line 9) | fn shim_skips_platform_checks_on_bypass() {

FILE: tests/acceptance/volta_install.rs
  function platform_with_node (line 11) | fn platform_with_node(node: &str) -> String {
  function platform_with_node_npm (line 25) | fn platform_with_node_npm(node: &str, npm: &str) -> String {
  constant NODE_VERSION_INFO (line 39) | const NODE_VERSION_INFO: &str = r#"[
  constant YARN_1_VERSION_INFO (line 122) | const YARN_1_VERSION_INFO: &str = r#"[
  constant YARN_1_VERSION_FIXTURES (line 130) | const YARN_1_VERSION_FIXTURES: [DistroMetadata; 4] = [
  constant YARN_BERRY_VERSION_INFO (line 153) | const YARN_BERRY_VERSION_INFO: &str = r#"{
  constant YARN_BERRY_VERSION_FIXTURES (line 164) | const YARN_BERRY_VERSION_FIXTURES: [DistroMetadata; 4] = [
  constant PNPM_VERSION_INFO (line 187) | const PNPM_VERSION_INFO: &str = r#"
  constant PNPM_VERSION_FIXTURES (line 199) | const PNPM_VERSION_FIXTURES: [DistroMetadata; 3] = [
  constant NPM_VERSION_INFO (line 217) | const NPM_VERSION_INFO: &str = r#"
  constant NPM_VERSION_FIXTURES (line 229) | const NPM_VERSION_FIXTURES: [DistroMetadata; 3] = [
  function install_node_informs_newer_npm (line 248) | fn install_node_informs_newer_npm() {
  function install_node_with_npm_hides_bundled_version (line 266) | fn install_node_with_npm_hides_bundled_version() {
  function install_npm_bundled_clears_npm (line 283) | fn install_npm_bundled_clears_npm() {
  function install_npm_bundled_reports_info (line 301) | fn install_npm_bundled_reports_info() {
  function install_npm_without_node_errors (line 317) | fn install_npm_without_node_errors() {
  function install_pnpm_without_node_errors (line 334) | fn install_pnpm_without_node_errors() {
  function install_yarn_without_node_errors (line 352) | fn install_yarn_without_node_errors() {
  function install_yarn_3_without_node_errors (line 369) | fn install_yarn_3_without_node_errors() {
  function install_node_with_shadowed_binary (line 388) | fn install_node_with_shadowed_binary() {

FILE: tests/acceptance/volta_pin.rs
  constant BASIC_PACKAGE_JSON (line 10) | const BASIC_PACKAGE_JSON: &str = r#"{
  constant PACKAGE_JSON_WITH_EMPTY_LINE (line 13) | const PACKAGE_JSON_WITH_EMPTY_LINE: &str = r#"{
  constant PACKAGE_JSON_WITH_EXTENDS (line 17) | const PACKAGE_JSON_WITH_EXTENDS: &str = r#"{
  function package_json_with_pinned_node (line 25) | fn package_json_with_pinned_node(node: &str) -> String {
  function package_json_with_pinned_node_npm (line 37) | fn package_json_with_pinned_node_npm(node: &str, npm: &str) -> String {
  function package_json_with_pinned_node_pnpm (line 50) | fn package_json_with_pinned_node_pnpm(node_version: &str, pnpm_version: ...
  function package_json_with_pinned_node_npm_pnpm (line 63) | fn package_json_with_pinned_node_npm_pnpm(
  function package_json_with_pinned_node_yarn (line 81) | fn package_json_with_pinned_node_yarn(node_version: &str, yarn_version: ...
  function package_json_with_pinned_node_npm_yarn (line 94) | fn package_json_with_pinned_node_npm_yarn(
  constant NODE_VERSION_INFO (line 112) | const NODE_VERSION_INFO: &str = r#"[
  constant YARN_1_VERSION_INFO (line 195) | const YARN_1_VERSION_INFO: &str = r#"{
  constant YARN_BERRY_VERSION_INFO (line 206) | const YARN_BERRY_VERSION_INFO: &str = r#"{
  constant YARN_1_VERSION_FIXTURES (line 217) | const YARN_1_VERSION_FIXTURES: [DistroMetadata; 4] = [
  constant YARN_BERRY_VERSION_FIXTURES (line 240) | const YARN_BERRY_VERSION_FIXTURES: [DistroMetadata; 4] = [
  constant PNPM_VERSION_INFO (line 263) | const PNPM_VERSION_INFO: &str = r#"
  constant PNPM_VERSION_FIXTURES (line 275) | const PNPM_VERSION_FIXTURES: [DistroMetadata; 3] = [
  constant NPM_VERSION_FIXTURES (line 293) | const NPM_VERSION_FIXTURES: [DistroMetadata; 3] = [
  constant NPM_VERSION_INFO (line 311) | const NPM_VERSION_INFO: &str = r#"
  constant VOLTA_LOGLEVEL (line 323) | const VOLTA_LOGLEVEL: &str = "VOLTA_LOGLEVEL";
  function pin_node (line 326) | fn pin_node() {
  function pin_node_reports_info (line 345) | fn pin_node_reports_info() {
  function pin_node_latest (line 362) | fn pin_node_latest() {
  function pin_node_no_version (line 381) | fn pin_node_no_version() {
  function pin_node_informs_newer_npm (line 400) | fn pin_node_informs_newer_npm() {
  function pin_node_with_npm_hides_bundled_version (line 418) | fn pin_node_with_npm_hides_bundled_version() {
  function pin_yarn_no_node (line 435) | fn pin_yarn_no_node() {
  function pin_yarn_1 (line 456) | fn pin_yarn_1() {
  function pin_yarn_2_is_error (line 476) | fn pin_yarn_2_is_error() {
  function pin_yarn_3 (line 501) | fn pin_yarn_3() {
  function pin_yarn_reports_info (line 522) | fn pin_yarn_reports_info() {
  function pin_yarn_latest (line 540) | fn pin_yarn_latest() {
  function pin_yarn_1_no_version (line 561) | fn pin_yarn_1_no_version() {
  function pin_yarn_3_no_version (line 582) | fn pin_yarn_3_no_version() {
  function pin_yarn_no_version (line 603) | fn pin_yarn_no_version() {
  function pin_yarn_1_missing_release (line 624) | fn pin_yarn_1_missing_release() {
  function pin_yarn_1_missing_release_v2 (line 644) | fn pin_yarn_1_missing_release_v2() {
  function pin_yarn_3_missing_release (line 664) | fn pin_yarn_3_missing_release() {
  function pin_yarn_3_missing_release_v2 (line 684) | fn pin_yarn_3_missing_release_v2() {
  function pin_yarn_leaves_npm (line 704) | fn pin_yarn_leaves_npm() {
  function pin_npm_no_node (line 724) | fn pin_npm_no_node() {
  function pin_npm (line 744) | fn pin_npm() {
  function pin_npm_reports_info (line 763) | fn pin_npm_reports_info() {
  function pin_npm_latest (line 780) | fn pin_npm_latest() {
  function pin_npm_no_version (line 799) | fn pin_npm_no_version() {
  function pin_npm_missing_release (line 818) | fn pin_npm_missing_release() {
  function pin_npm_bundled_removes_npm (line 838) | fn pin_npm_bundled_removes_npm() {
  function pin_npm_bundled_reports_info (line 856) | fn pin_npm_bundled_reports_info() {
  function pin_node_and_yarn1 (line 872) | fn pin_node_and_yarn1() {
  function pin_node_and_yarn3 (line 894) | fn pin_node_and_yarn3() {
  function pin_node_does_not_remove_trailing_newline (line 917) | fn pin_node_does_not_remove_trailing_newline() {
  function pin_node_does_not_overwrite_extends (line 933) | fn pin_node_does_not_overwrite_extends() {
  function pin_pnpm_no_node (line 952) | fn pin_pnpm_no_node() {
  function pin_pnpm (line 973) | fn pin_pnpm() {
  function pin_pnpm_reports_info (line 993) | fn pin_pnpm_reports_info() {
  function pin_pnpm_latest (line 1011) | fn pin_pnpm_latest() {
  function pin_pnpm_no_version (line 1031) | fn pin_pnpm_no_version() {
  function pin_pnpm_missing_release (line 1051) | fn pin_pnpm_missing_release() {
  function pin_node_and_pnpm (line 1072) | fn pin_node_and_pnpm() {
  function pin_pnpm_leaves_npm (line 1094) | fn pin_pnpm_leaves_npm() {

FILE: tests/acceptance/volta_run.rs
  function package_json_with_pinned_node (line 10) | fn package_json_with_pinned_node(node: &str) -> String {
  function package_json_with_pinned_node_npm (line 22) | fn package_json_with_pinned_node_npm(node: &str, npm: &str) -> String {
  function package_json_with_pinned_node_pnpm (line 35) | fn package_json_with_pinned_node_pnpm(node_version: &str, pnpm_version: ...
  function package_json_with_pinned_node_yarn (line 48) | fn package_json_with_pinned_node_yarn(node_version: &str, yarn_version: ...
  constant NODE_VERSION_INFO (line 61) | const NODE_VERSION_INFO: &str = r#"[
  constant PNPM_VERSION_INFO (line 144) | const PNPM_VERSION_INFO: &str = r#"
  constant PNPM_VERSION_FIXTURES (line 155) | const PNPM_VERSION_FIXTURES: [DistroMetadata; 2] = [
  constant YARN_1_VERSION_INFO (line 168) | const YARN_1_VERSION_INFO: &str = r#"{
  constant YARN_1_VERSION_FIXTURES (line 179) | const YARN_1_VERSION_FIXTURES: [DistroMetadata; 4] = [
  constant YARN_BERRY_VERSION_INFO (line 202) | const YARN_BERRY_VERSION_INFO: &str = r#"{
  constant YARN_BERRY_VERSION_FIXTURES (line 213) | const YARN_BERRY_VERSION_FIXTURES: [DistroMetadata; 4] = [
  constant NPM_VERSION_FIXTURES (line 236) | const NPM_VERSION_FIXTURES: [DistroMetadata; 3] = [
  constant NPM_VERSION_INFO (line 254) | const NPM_VERSION_INFO: &str = r#"
  constant VOLTA_LOGLEVEL (line 266) | const VOLTA_LOGLEVEL: &str = "VOLTA_LOGLEVEL";
  function command_line_node (line 269) | fn command_line_node() {
  function inherited_node (line 285) | fn inherited_node() {
  function command_line_npm (line 302) | fn command_line_npm() {
  function inherited_npm (line 320) | fn inherited_npm() {
  function force_bundled_npm (line 339) | fn force_bundled_npm() {
  function command_line_yarn_1 (line 358) | fn command_line_yarn_1() {
  function command_line_yarn_3 (line 382) | fn command_line_yarn_3() {
  function inherited_yarn_1 (line 402) | fn inherited_yarn_1() {
  function inherited_yarn_3 (line 421) | fn inherited_yarn_3() {
  function force_no_yarn (line 442) | fn force_no_yarn() {
  function command_line_pnpm (line 461) | fn command_line_pnpm() {
  function inherited_pnpm (line 480) | fn inherited_pnpm() {
  function force_no_pnpm (line 500) | fn force_no_pnpm() {

FILE: tests/acceptance/volta_uninstall.rs
  constant PKG_CONFIG_BASIC (line 8) | const PKG_CONFIG_BASIC: &str = r#"{
  constant PKG_CONFIG_NO_BINS (line 23) | const PKG_CONFIG_NO_BINS: &str = r#"{
  function bin_config (line 35) | fn bin_config(name: &str) -> String {
  constant VOLTA_LOGLEVEL (line 52) | const VOLTA_LOGLEVEL: &str = "VOLTA_LOGLEVEL";
  function uninstall_nonexistent_pkg (line 55) | fn uninstall_nonexistent_pkg() {
  function uninstall_package_basic (line 68) | fn uninstall_package_basic() {
  function uninstall_package_basic_with_version (line 102) | fn uninstall_package_basic_with_version() {
  function uninstall_package_no_bins (line 124) | fn uninstall_package_no_bins() {
  function uninstall_package_no_image (line 150) | fn uninstall_package_no_image() {
  function uninstall_package_orphaned_bins (line 181) | fn uninstall_package_orphaned_bins() {
  function uninstall_runtime (line 209) | fn uninstall_runtime() {

FILE: tests/smoke/autodownload.rs
  function autodownload_node (line 39) | fn autodownload_node() {
  function autodownload_npm (line 51) | fn autodownload_npm() {
  function autodownload_yarn_1 (line 63) | fn autodownload_yarn_1() {
  function autodownload_yarn_3 (line 75) | fn autodownload_yarn_3() {

FILE: tests/smoke/direct_install.rs
  function npm_global_install (line 7) | fn npm_global_install() {
  function yarn_global_add (line 46) | fn yarn_global_add() {

FILE: tests/smoke/direct_upgrade.rs
  function npm_global_update (line 8) | fn npm_global_update() {
  function yarn_global_update (line 50) | fn yarn_global_update() {

FILE: tests/smoke/npm_link.rs
  constant PACKAGE_JSON (line 6) | const PACKAGE_JSON: &str = r#"
  constant INDEX_JS (line 15) | const INDEX_JS: &str = r#"#!/usr/bin/env node
  function link_unlink_local_project (line 21) | fn link_unlink_local_project() {
  function link_global_into_current_project (line 48) | fn link_global_into_current_project() {

FILE: tests/smoke/package_migration.rs
  constant LEGACY_PACKAGE_CONFIG (line 7) | const LEGACY_PACKAGE_CONFIG: &str = r#"{
  constant LEGACY_BIN_CONFIG (line 23) | const LEGACY_BIN_CONFIG: &str = r#"{
  constant COWSAY_HELLO (line 41) | const COWSAY_HELLO: &str = r#" _______
  function legacy_package_upgrade (line 51) | fn legacy_package_upgrade() {

FILE: tests/smoke/support/temp_project.rs
  type FileBuilder (line 14) | pub struct FileBuilder {
    method new (line 20) | pub fn new(path: PathBuf, contents: &str) -> FileBuilder {
    method build (line 27) | pub fn build(&self) {
    method dirname (line 36) | fn dirname(&self) -> &Path {
  type EnvVar (line 41) | pub struct EnvVar {
    method new (line 47) | pub fn new(name: &str, value: &str) -> Self {
  type TempProjectBuilder (line 56) | pub struct TempProjectBuilder {
    method root (line 63) | pub fn root(&self) -> PathBuf {
    method new (line 67) | pub fn new(root: PathBuf) -> TempProjectBuilder {
    method package_json (line 79) | pub fn package_json(mut self, contents: &str) -> Self {
    method project_file (line 86) | pub fn project_file(mut self, path: &str, contents: &str) -> Self {
    method volta_home_file (line 93) | pub fn volta_home_file(mut self, path: &str, contents: &str) -> Self {
    method env (line 100) | pub fn env(mut self, name: &str, value: &str) -> Self {
    method build (line 106) | pub fn build(mut self) -> TempProject {
    method rm_root (line 153) | fn rm_root(&self) {
  function home_dir (line 160) | fn home_dir(root: PathBuf) -> PathBuf {
  function volta_home (line 163) | fn volta_home(root: PathBuf) -> PathBuf {
  function volta_file (line 166) | fn volta_file(root: PathBuf) -> PathBuf {
  function shim_executable (line 169) | fn shim_executable(root: PathBuf) -> PathBuf {
  function default_hooks_file (line 172) | fn default_hooks_file(root: PathBuf) -> PathBuf {
  function volta_tmp_dir (line 175) | fn volta_tmp_dir(root: PathBuf) -> PathBuf {
  function volta_bin_dir (line 178) | fn volta_bin_dir(root: PathBuf) -> PathBuf {
  function volta_tools_dir (line 181) | fn volta_tools_dir(root: PathBuf) -> PathBuf {
  function inventory_dir (line 184) | fn inventory_dir(root: PathBuf) -> PathBuf {
  function default_toolchain_dir (line 187) | fn default_toolchain_dir(root: PathBuf) -> PathBuf {
  function image_dir (line 190) | fn image_dir(root: PathBuf) -> PathBuf {
  function node_image_root_dir (line 193) | fn node_image_root_dir(root: PathBuf) -> PathBuf {
  function node_image_dir (line 196) | fn node_image_dir(node: &str, root: PathBuf) -> PathBuf {
  function node_image_bin_dir (line 199) | fn node_image_bin_dir(node: &str, root: PathBuf) -> PathBuf {
  function npm_image_root_dir (line 202) | fn npm_image_root_dir(root: PathBuf) -> PathBuf {
  function npm_image_dir (line 205) | fn npm_image_dir(version: &str, root: PathBuf) -> PathBuf {
  function npm_image_bin_dir (line 208) | fn npm_image_bin_dir(version: &str, root: PathBuf) -> PathBuf {
  function yarn_image_root_dir (line 211) | fn yarn_image_root_dir(root: PathBuf) -> PathBuf {
  function yarn_image_dir (line 214) | fn yarn_image_dir(version: &str, root: PathBuf) -> PathBuf {
  function package_image_root_dir (line 217) | fn package_image_root_dir(root: PathBuf) -> PathBuf {
  function node_inventory_dir (line 220) | fn node_inventory_dir(root: PathBuf) -> PathBuf {
  function npm_inventory_dir (line 223) | fn npm_inventory_dir(root: PathBuf) -> PathBuf {
  function yarn_inventory_dir (line 226) | fn yarn_inventory_dir(root: PathBuf) -> PathBuf {
  function package_inventory_dir (line 229) | fn package_inventory_dir(root: PathBuf) -> PathBuf {
  function cache_dir (line 232) | fn cache_dir(root: PathBuf) -> PathBuf {
  function node_cache_dir (line 235) | fn node_cache_dir(root: PathBuf) -> PathBuf {
  function package_json_file (line 238) | fn package_json_file(mut root: PathBuf) -> PathBuf {
  function shim_file (line 242) | fn shim_file(name: &str, root: PathBuf) -> PathBuf {
  function package_image_dir (line 245) | fn package_image_dir(name: &str, root: PathBuf) -> PathBuf {
  function default_platform_file (line 248) | fn default_platform_file(root: PathBuf) -> PathBuf {
  function node_distro_file_name (line 251) | pub fn node_distro_file_name(version: &str) -> String {
  function npm_distro_file_name (line 255) | fn npm_distro_file_name(version: &str) -> String {
  function yarn_distro_file_name (line 258) | fn yarn_distro_file_name(version: &str) -> String {
  function package_distro_file_name (line 261) | fn package_distro_file_name(name: &str, version: &str) -> String {
  type TempProject (line 265) | pub struct TempProject {
    method root (line 273) | pub fn root(&self) -> PathBuf {
    method process (line 283) | pub fn process<T: AsRef<OsStr>>(&self, program: T) -> ProcessBuilder {
    method volta (line 306) | pub fn volta(&self, cmd: &str) -> ProcessBuilder {
    method node (line 313) | pub fn node(&self, cmd: &str) -> ProcessBuilder {
    method node_exe (line 319) | pub fn node_exe(&self) -> PathBuf {
    method yarn (line 324) | pub fn yarn(&self, cmd: &str) -> ProcessBuilder {
    method yarn_exe (line 330) | pub fn yarn_exe(&self) -> PathBuf {
    method npm (line 335) | pub fn npm(&self, cmd: &str) -> ProcessBuilder {
    method npm_exe (line 341) | pub fn npm_exe(&self) -> PathBuf {
    method exec_shim (line 346) | pub fn exec_shim(&self, exe: &str, cmd: &str) -> ProcessBuilder {
    method node_version_is_fetched (line 354) | pub fn node_version_is_fetched(&self, version: &str) -> bool {
    method node_version_is_unpacked (line 361) | pub fn node_version_is_unpacked(&self, version: &str) -> bool {
    method assert_node_version_is_installed (line 367) | pub fn assert_node_version_is_installed(&self, version: &str) -> () {
    method yarn_version_is_fetched (line 376) | pub fn yarn_version_is_fetched(&self, version: &str) -> bool {
    method yarn_version_is_unpacked (line 383) | pub fn yarn_version_is_unpacked(&self, version: &str) -> bool {
    method assert_yarn_version_is_installed (line 389) | pub fn assert_yarn_version_is_installed(&self, version: &str) -> () {
    method npm_version_is_fetched (line 398) | pub fn npm_version_is_fetched(&self, version: &str) -> bool {
    method npm_version_is_unpacked (line 405) | pub fn npm_version_is_unpacked(&self, version: &str) -> bool {
    method assert_npm_version_is_installed (line 410) | pub fn assert_npm_version_is_installed(&self, version: &str) -> () {
    method package_is_installed (line 419) | pub fn package_is_installed(&self, name: &str) -> bool {
    method shim_exists (line 425) | pub fn shim_exists(&self, name: &str) -> bool {
    method project_path_exists (line 430) | pub fn project_path_exists(&self, path: &str) -> bool {
  method drop (line 436) | fn drop(&mut self) {
  function temp_project (line 442) | pub fn temp_project() -> TempProjectBuilder {
  function cargo_dir (line 447) | pub fn cargo_dir() -> PathBuf {
  function volta_exe (line 462) | fn volta_exe() -> PathBuf {
  function shim_exe (line 466) | fn shim_exe() -> PathBuf {
  function split_and_add_args (line 470) | fn split_and_add_args(p: &mut ProcessBuilder, s: &str) {
  function read_file_to_string (line 479) | fn read_file_to_string(file_path: PathBuf) -> String {

FILE: tests/smoke/volta_fetch.rs
  function fetch_node (line 8) | fn fetch_node() {
  function fetch_yarn_1 (line 17) | fn fetch_yarn_1() {
  function fetch_yarn_3 (line 26) | fn fetch_yarn_3() {
  function fetch_npm (line 35) | fn fetch_npm() {

FILE: tests/smoke/volta_install.rs
  function install_node (line 9) | fn install_node() {
  function install_node_lts (line 25) | fn install_node_lts() {
  function install_node_concurrent (line 34) | fn install_node_concurrent() {
  function install_yarn (line 52) | fn install_yarn() {
  function install_old_yarn (line 69) | fn install_old_yarn() {
  function install_yarn_concurrent (line 87) | fn install_yarn_concurrent() {
  function install_npm (line 107) | fn install_npm() {
  function install_npm_concurrent (line 130) | fn install_npm_concurrent() {
  constant COWSAY_HELLO (line 149) | const COWSAY_HELLO: &'static str = r#" _______
  function install_package (line 159) | fn install_package() {
  function install_package_concurrent (line 176) | fn install_package_concurrent() {
  function install_scoped_package (line 196) | fn install_scoped_package() {
  function install_package_tag_version (line 213) | fn install_package_tag_version() {

FILE: tests/smoke/volta_run.rs
  constant PACKAGE_JSON (line 8) | const PACKAGE_JSON: &str = r#"{
  function run_node (line 18) | fn run_node() {
  function run_npm (line 28) | fn run_npm() {
  function run_yarn_1 (line 38) | fn run_yarn_1() {
  function run_yarn_3 (line 48) | fn run_yarn_3() {
  function inherits_project_platform (line 58) | fn inherits_project_platform() {
  function run_environment (line 68) | fn run_environment() {
Condensed preview — 226 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (1,092K chars).
[
  {
    "path": ".cargo/config.toml",
    "chars": 167,
    "preview": "[target.x86_64-pc-windows-msvc]\r\nrustflags = [\"-C\", \"target-feature=+crt-static\"]\r\n[target.aarch64-pc-windows-msvc]\r\nrus"
  },
  {
    "path": ".github/dependabot.yml",
    "chars": 170,
    "preview": "version: 2\nupdates:\n  - package-ecosystem: \"cargo\"\n    open-pull-requests-limit: 5\n    schedule:\n      interval: \"daily\""
  },
  {
    "path": ".github/workflows/api-docs.yml",
    "chars": 1119,
    "preview": "on:\n  push:\n    branches:\n      - main\n\nname: API Docs\n\njobs:\n  publish:\n    name: Build and publish\n    runs-on: ubuntu"
  },
  {
    "path": ".github/workflows/release.yml",
    "chars": 9358,
    "preview": "on:\n  push:\n    tags:\n      - v*\n  pull_request:\n    branches:\n      - main\n\nname: Production\n\njobs:\n  linux:\n    name: "
  },
  {
    "path": ".github/workflows/test.yml",
    "chars": 1973,
    "preview": "on:\n  push:\n    branches:\n      - main\n  pull_request:\n    branches:\n      - main\n\nname: Test\n\njobs:\n  tests:\n    strate"
  },
  {
    "path": ".gitignore",
    "chars": 876,
    "preview": "/target/\n**/*.rs.bk\nNotion.msi\nVolta.msi\ndev/windows/*.log\ndev/windows/Notion.wixobj\ndev/windows/Volta.wixobj\ndev/window"
  },
  {
    "path": ".vscode/launch.json",
    "chars": 885,
    "preview": "{\n  \"version\": \"0.2.0\",\n  \"configurations\": [\n    {\n      \"type\": \"lldb\",\n      \"request\": \"launch\",\n      \"name\": \"Carg"
  },
  {
    "path": ".vscode/settings.json",
    "chars": 34,
    "preview": "{\n  \"editor.formatOnSave\": true\n}\n"
  },
  {
    "path": "CODE_OF_CONDUCT.md",
    "chars": 3196,
    "preview": "# Contributor Covenant Code of Conduct\n\n## Our Pledge\n\nIn the interest of fostering an open and welcoming environment, w"
  },
  {
    "path": "COMPATIBILITY.md",
    "chars": 645,
    "preview": "# Compatibility\n\nVolta currently tests against the following platforms, and will treat it as a breaking change to drop s"
  },
  {
    "path": "CONTRIBUTING.md",
    "chars": 47,
    "preview": "Please see https://docs.volta.sh/contributing/\n"
  },
  {
    "path": "Cargo.toml",
    "chars": 1246,
    "preview": "[package]\nname = \"volta\"\nversion = \"2.0.2\"\nauthors = [\"David Herman <david.herman@gmail.com>\", \"Charles Pierce <cpierce."
  },
  {
    "path": "LICENSE",
    "chars": 1652,
    "preview": "BSD 2-CLAUSE LICENSE\n\nCopyright (c) 2017, The Volta Contributors.\nAll rights reserved.\n\nThis product includes:\n\nContribu"
  },
  {
    "path": "README.md",
    "chars": 3166,
    "preview": "<p align=\"center\">\n  <a href=\"https://www.volta.sh/\">\n    <img alt=\"Volta\" src=\"./volta.png?raw=true\" width=\"360\">\n  </a"
  },
  {
    "path": "RELEASES.md",
    "chars": 12360,
    "preview": "# Version 2.0.2\n\n- Dependency updates\n- Improvements to header handling for HTTP requests (#1822, #1877)\n\n# Version 2.0."
  },
  {
    "path": "ci/build-linux.sh",
    "chars": 325,
    "preview": "#!/bin/bash\n\nset -e\n\n# Activate the upgraded versions of GCC and binutils\n# See https://linux.web.cern.ch/centos7/docs/s"
  },
  {
    "path": "ci/build-macos.sh",
    "chars": 578,
    "preview": "#!/bin/bash\n\nset -e\n\necho \"Building Volta\"\n\nMACOSX_DEPLOYMENT_TARGET=11.0 cargo build --release --target=aarch64-apple-d"
  },
  {
    "path": "ci/docker/Dockerfile",
    "chars": 609,
    "preview": "FROM cern/cc7-base\n\n# This repo file references a URL that is no longer valid. It also isn't used by the build\n# toolcha"
  },
  {
    "path": "ci/volta.manifest",
    "chars": 31,
    "preview": "volta\nvolta-shim\nvolta-migrate\n"
  },
  {
    "path": "crates/archive/Cargo.toml",
    "chars": 848,
    "preview": "[package]\nname = \"archive\"\nversion = \"0.1.0\"\nauthors = [\"David Herman <david.herman@gmail.com>\"]\nedition = \"2021\"\n\n[depe"
  },
  {
    "path": "crates/archive/src/lib.rs",
    "chars": 3383,
    "preview": "//! This crate provides types for fetching and unpacking compressed\n//! archives in tarball or zip format.\nuse std::fs::"
  },
  {
    "path": "crates/archive/src/tarball.rs",
    "chars": 2870,
    "preview": "//! Provides types and functions for fetching and unpacking a Node installation\n//! tarball in Unix operating systems.\n\n"
  },
  {
    "path": "crates/archive/src/zip.rs",
    "chars": 2886,
    "preview": "//! Provides types and functions for fetching and unpacking a Node installation\n//! zip file in Windows operating system"
  },
  {
    "path": "crates/fs-utils/Cargo.toml",
    "chars": 131,
    "preview": "[package]\nname = \"fs-utils\"\nversion = \"0.1.0\"\nauthors = [\"Michael Stewart <mikrostew@gmail.com>\"]\nedition = \"2021\"\n\n[dep"
  },
  {
    "path": "crates/fs-utils/src/lib.rs",
    "chars": 645,
    "preview": "//! This crate provides utilities for operating on the filesystem.\n\nuse std::fs;\nuse std::io;\nuse std::path::Path;\n\n/// "
  },
  {
    "path": "crates/progress-read/Cargo.toml",
    "chars": 136,
    "preview": "[package]\nname = \"progress-read\"\nversion = \"0.1.0\"\nauthors = [\"David Herman <david.herman@gmail.com>\"]\nedition = \"2021\"\n"
  },
  {
    "path": "crates/progress-read/src/lib.rs",
    "chars": 1771,
    "preview": "//! This crate provides an adapter for the `std::io::Read` trait to\n//! allow reporting incremental progress to a callba"
  },
  {
    "path": "crates/test-support/Cargo.toml",
    "chars": 212,
    "preview": "[package]\nname = \"test-support\"\nversion = \"0.1.0\"\nauthors = [\"David Herman <david.herman@gmail.com>\"]\nedition = \"2021\"\n\n"
  },
  {
    "path": "crates/test-support/src/lib.rs",
    "chars": 305,
    "preview": "//! Utilities to use with acceptance tests in Volta.\n\n#[macro_export]\nmacro_rules! ok_or_panic {\n    { $e:expr } => {\n  "
  },
  {
    "path": "crates/test-support/src/matchers.rs",
    "chars": 24151,
    "preview": "use std::fmt;\nuse std::process::Output;\nuse std::str;\n\nuse crate::process::ProcessBuilder;\n\nuse hamcrest2::core::{MatchR"
  },
  {
    "path": "crates/test-support/src/paths.rs",
    "chars": 4067,
    "preview": "use std::cell::Cell;\nuse std::env;\nuse std::fs;\nuse std::path::{Path, PathBuf};\nuse std::sync::atomic::{AtomicUsize, Ord"
  },
  {
    "path": "crates/test-support/src/process.rs",
    "chars": 7073,
    "preview": "use std::collections::HashMap;\nuse std::env;\nuse std::ffi::{OsStr, OsString};\nuse std::fmt;\nuse std::path::Path;\nuse std"
  },
  {
    "path": "crates/validate-npm-package-name/Cargo.toml",
    "chars": 218,
    "preview": "[package]\nname = \"validate-npm-package-name\"\nversion = \"0.1.0\"\nauthors = [\"Chris Krycho <hello@chriskrycho.com>\"]\neditio"
  },
  {
    "path": "crates/validate-npm-package-name/src/lib.rs",
    "chars": 9829,
    "preview": "//! A Rust implementation of the validation rules from the core JS package\n//! [`validate-npm-package-name`](https://git"
  },
  {
    "path": "crates/volta-core/Cargo.toml",
    "chars": 1853,
    "preview": "[package]\nname = \"volta-core\"\nversion = \"0.1.0\"\nauthors = [\"David Herman <david.herman@gmail.com>\"]\nedition = \"2021\"\n\n[f"
  },
  {
    "path": "crates/volta-core/fixtures/basic/package.json",
    "chars": 412,
    "preview": "{\n  \"name\": \"basic-project\",\n  \"version\": \"0.0.7\",\n  \"description\": \"Testing that manifest pulls things out of this corr"
  },
  {
    "path": "crates/volta-core/fixtures/basic/subdir/.gitkeep",
    "chars": 0,
    "preview": ""
  },
  {
    "path": "crates/volta-core/fixtures/cycle-1/package.json",
    "chars": 221,
    "preview": "{\n  \"name\": \"cycle-1-project\",\n  \"version\": \"0.0.1\",\n  \"description\": \"Testing that project correctly detects a cycle be"
  },
  {
    "path": "crates/volta-core/fixtures/cycle-1/volta.json",
    "chars": 53,
    "preview": "{\n  \"volta\": {\n    \"extends\": \"./package.json\"\n  }\n}\n"
  },
  {
    "path": "crates/volta-core/fixtures/cycle-2/package.json",
    "chars": 245,
    "preview": "{\n  \"name\": \"cycle-2-project\",\n  \"version\": \"0.0.1\",\n  \"description\": \"Testing that project correctly detects a cycle be"
  },
  {
    "path": "crates/volta-core/fixtures/cycle-2/workspace-1.json",
    "chars": 57,
    "preview": "{\n  \"volta\": {\n    \"extends\": \"./workspace-2.json\"\n  }\n}\n"
  },
  {
    "path": "crates/volta-core/fixtures/cycle-2/workspace-2.json",
    "chars": 57,
    "preview": "{\n  \"volta\": {\n    \"extends\": \"./workspace-1.json\"\n  }\n}\n"
  },
  {
    "path": "crates/volta-core/fixtures/hooks/bins.json",
    "chars": 654,
    "preview": "{\n  \"node\": {\n    \"distro\": {\n      \"bin\": \"/some/bin/for/node/distro\"\n    },\n    \"latest\": {\n      \"bin\": \"/some/bin/fo"
  },
  {
    "path": "crates/volta-core/fixtures/hooks/event_url.json",
    "chars": 79,
    "preview": "{\n  \"events\": {\n    \"publish\": {\n      \"url\": \"https://google.com\"\n    }\n  }\n}\n"
  },
  {
    "path": "crates/volta-core/fixtures/hooks/format_github.json",
    "chars": 445,
    "preview": "{\n  \"node\": {\n    \"index\": {\n      \"prefix\": \"http://localhost/node/index/\",\n      \"format\": \"github\"\n    }\n  },\n  \"npm\""
  },
  {
    "path": "crates/volta-core/fixtures/hooks/format_npm.json",
    "chars": 433,
    "preview": "{\n  \"node\": {\n    \"index\": {\n      \"prefix\": \"http://localhost/node/index/\",\n      \"format\": \"npm\"\n    }\n  },\n  \"npm\": {"
  },
  {
    "path": "crates/volta-core/fixtures/hooks/prefixes.json",
    "chars": 684,
    "preview": "{\n  \"node\": {\n    \"distro\": {\n      \"prefix\": \"http://localhost/node/distro/\"\n    },\n    \"latest\": {\n      \"prefix\": \"ht"
  },
  {
    "path": "crates/volta-core/fixtures/hooks/project/.volta/hooks.json",
    "chars": 278,
    "preview": "{\n  \"node\": {\n    \"distro\": {\n      \"bin\": \"/some/bin/for/node/distro\"\n    },\n    \"latest\": {\n      \"bin\": \"/some/bin/fo"
  },
  {
    "path": "crates/volta-core/fixtures/hooks/project/package.json",
    "chars": 73,
    "preview": "{\n  \"this file\": \"causes this directory to be recognized as a project\"\n}\n"
  },
  {
    "path": "crates/volta-core/fixtures/hooks/templates.json",
    "chars": 810,
    "preview": "{\n  \"node\": {\n    \"distro\": {\n      \"template\": \"http://localhost/node/distro/{{version}}/\"\n    },\n    \"latest\": {\n     "
  },
  {
    "path": "crates/volta-core/fixtures/nested/package.json",
    "chars": 327,
    "preview": "{\n  \"name\": \"nested-project\",\n  \"version\": \"0.0.1\",\n  \"description\": \"Testing that project correctly detects a nested wo"
  },
  {
    "path": "crates/volta-core/fixtures/nested/subproject/inner_project/package.json",
    "chars": 321,
    "preview": "{\n  \"name\": \"inner-project\",\n  \"version\": \"0.0.1\",\n  \"description\": \"Testing that project correctly detects a nested wor"
  },
  {
    "path": "crates/volta-core/fixtures/nested/subproject/package.json",
    "chars": 329,
    "preview": "{\n  \"name\": \"subproject\",\n  \"version\": \"0.0.1\",\n  \"description\": \"Testing that project correctly detects a nested worksp"
  },
  {
    "path": "crates/volta-core/fixtures/no_toolchain/package.json",
    "chars": 330,
    "preview": "{\n  \"name\": \"basic-project\",\n  \"version\": \"0.0.7\",\n  \"description\": \"Testing that manifest pulls things out of this corr"
  },
  {
    "path": "crates/volta-core/fixtures/yarn/pnp-cjs/.pnp.cjs",
    "chars": 17,
    "preview": "// plug and play\n"
  },
  {
    "path": "crates/volta-core/fixtures/yarn/pnp-cjs/package.json",
    "chars": 216,
    "preview": "{\n  \"name\": \"plug-n-play-cjs\",\n  \"version\": \"2.0.0\",\n  \"description\": \"Testing that Plug-n-Play things work\",\n  \"license"
  },
  {
    "path": "crates/volta-core/fixtures/yarn/pnp-js/.pnp.js",
    "chars": 17,
    "preview": "// plug and play\n"
  },
  {
    "path": "crates/volta-core/fixtures/yarn/pnp-js/package.json",
    "chars": 215,
    "preview": "{\n  \"name\": \"plug-n-play-js\",\n  \"version\": \"2.0.0\",\n  \"description\": \"Testing that Plug-n-Play things work\",\n  \"license\""
  },
  {
    "path": "crates/volta-core/fixtures/yarn/yarnrc-yml/.yarnrc.yml",
    "chars": 39,
    "preview": "yarnPath: .yarn/releases/yarn-3.3.0.cjs"
  },
  {
    "path": "crates/volta-core/fixtures/yarn/yarnrc-yml/package.json",
    "chars": 210,
    "preview": "{\n  \"name\": \"yarnrc-yml\",\n  \"version\": \"2.0.0\",\n  \"description\": \"Testing that Yarn berry things work\",\n  \"license\": \"To"
  },
  {
    "path": "crates/volta-core/src/command.rs",
    "chars": 883,
    "preview": "use std::ffi::OsStr;\nuse std::process::Command;\n\nuse cfg_if::cfg_if;\n\ncfg_if! {\n    if #[cfg(windows)] {\n        pub fn "
  },
  {
    "path": "crates/volta-core/src/error/kind.rs",
    "chars": 53286,
    "preview": "use std::fmt;\nuse std::path::PathBuf;\n\nuse super::ExitCode;\nuse crate::style::{text_width, tool_version};\nuse crate::too"
  },
  {
    "path": "crates/volta-core/src/error/mod.rs",
    "chars": 2942,
    "preview": "use std::error::Error;\nuse std::fmt;\nuse std::process::exit;\n\nmod kind;\nmod reporter;\n\npub use kind::ErrorKind;\npub use "
  },
  {
    "path": "crates/volta-core/src/error/reporter.rs",
    "chars": 3272,
    "preview": "use std::env::args_os;\nuse std::error::Error;\nuse std::fs::File;\nuse std::io::Write;\nuse std::path::PathBuf;\n\nuse super:"
  },
  {
    "path": "crates/volta-core/src/event.rs",
    "chars": 6297,
    "preview": "//! Events for the sessions in executables and shims and everything\n\nuse std::env;\nuse std::time::{SystemTime, UNIX_EPOC"
  },
  {
    "path": "crates/volta-core/src/fs.rs",
    "chars": 6466,
    "preview": "//! Provides utilities for operating on the filesystem.\n\nuse std::fs::{self, create_dir_all, read_dir, DirEntry, File, M"
  },
  {
    "path": "crates/volta-core/src/hook/mod.rs",
    "chars": 24039,
    "preview": "//! Provides types for working with Volta hooks.\n\nuse std::borrow::Cow;\nuse std::fs::File;\nuse std::iter::once;\nuse std:"
  },
  {
    "path": "crates/volta-core/src/hook/serial.rs",
    "chars": 6628,
    "preview": "use std::marker::PhantomData;\nuse std::path::Path;\n\nuse super::tool;\nuse super::RegistryFormat;\nuse crate::error::{Error"
  },
  {
    "path": "crates/volta-core/src/hook/tool.rs",
    "chars": 9432,
    "preview": "//! Types representing Volta Tool Hooks.\n\nuse std::ffi::OsString;\nuse std::path::{Path, PathBuf};\nuse std::process::Stdi"
  },
  {
    "path": "crates/volta-core/src/inventory.rs",
    "chars": 4055,
    "preview": "//! Provides types for working with Volta's _inventory_, the local repository\n//! of available tool versions.\n\nuse std::"
  },
  {
    "path": "crates/volta-core/src/layout/mod.rs",
    "chars": 1793,
    "preview": "use std::env;\nuse std::path::PathBuf;\n\nuse crate::error::{Context, ErrorKind, Fallible};\nuse cfg_if::cfg_if;\nuse dunce::"
  },
  {
    "path": "crates/volta-core/src/layout/unix.rs",
    "chars": 384,
    "preview": "use std::path::PathBuf;\n\nuse super::volta_home;\nuse crate::error::{ErrorKind, Fallible};\n\npub(super) fn default_home_dir"
  },
  {
    "path": "crates/volta-core/src/layout/windows.rs",
    "chars": 464,
    "preview": "use std::path::PathBuf;\n\nuse super::{volta_home, volta_install};\nuse crate::error::{ErrorKind, Fallible};\n\npub(super) fn"
  },
  {
    "path": "crates/volta-core/src/lib.rs",
    "chars": 418,
    "preview": "//! The main implementation crate for the core of Volta.\n\nmod command;\npub mod error;\npub mod event;\npub mod fs;\nmod hoo"
  },
  {
    "path": "crates/volta-core/src/log.rs",
    "chars": 5494,
    "preview": "//! This module provides a custom Logger implementation for use with the `log` crate\nuse console::style;\nuse log::{trace"
  },
  {
    "path": "crates/volta-core/src/monitor.rs",
    "chars": 3158,
    "preview": "use std::env;\nuse std::io::Write;\nuse std::path::PathBuf;\nuse std::process::{Child, Stdio};\n\nuse log::debug;\nuse tempfil"
  },
  {
    "path": "crates/volta-core/src/platform/image.rs",
    "chars": 2464,
    "preview": "use std::ffi::OsString;\nuse std::path::PathBuf;\n\nuse super::{build_path_error, Sourced};\nuse crate::error::{Context, Fal"
  },
  {
    "path": "crates/volta-core/src/platform/mod.rs",
    "chars": 9410,
    "preview": "use std::env;\nuse std::fmt;\n\nuse crate::error::{ErrorKind, Fallible};\nuse crate::session::Session;\nuse crate::tool::{Nod"
  },
  {
    "path": "crates/volta-core/src/platform/system.rs",
    "chars": 794,
    "preview": "use std::ffi::OsString;\n\nuse super::build_path_error;\nuse crate::error::{Context, Fallible};\nuse crate::layout::env_path"
  },
  {
    "path": "crates/volta-core/src/platform/tests.rs",
    "chars": 15589,
    "preview": "use super::*;\nuse crate::layout::volta_home;\n#[cfg(windows)]\nuse crate::layout::volta_install;\nuse node_semver::Version;"
  },
  {
    "path": "crates/volta-core/src/project/mod.rs",
    "chars": 9731,
    "preview": "//! Provides the `Project` type, which represents a Node project tree in\n//! the filesystem.\n\nuse std::env;\nuse std::ffi"
  },
  {
    "path": "crates/volta-core/src/project/serial.rs",
    "chars": 5867,
    "preview": "use std::collections::HashMap;\nuse std::fmt;\nuse std::fs::{read_to_string, File};\nuse std::io::Write;\nuse std::path::{Pa"
  },
  {
    "path": "crates/volta-core/src/project/tests.rs",
    "chars": 8856,
    "preview": "use std::path::PathBuf;\n\nuse super::*;\n\nfn fixture_path(fixture_dirs: &[&str]) -> PathBuf {\n    let mut cargo_manifest_d"
  },
  {
    "path": "crates/volta-core/src/run/binary.rs",
    "chars": 7279,
    "preview": "use std::env;\nuse std::ffi::{OsStr, OsString};\nuse std::path::PathBuf;\n\nuse super::executor::{Executor, ToolCommand, Too"
  },
  {
    "path": "crates/volta-core/src/run/executor.rs",
    "chars": 18226,
    "preview": "use std::collections::HashMap;\nuse std::ffi::OsStr;\n#[cfg(unix)]\nuse std::os::unix::process::ExitStatusExt;\n#[cfg(window"
  },
  {
    "path": "crates/volta-core/src/run/mod.rs",
    "chars": 5527,
    "preview": "use std::collections::HashMap;\nuse std::env::{self, ArgsOs};\nuse std::ffi::{OsStr, OsString};\nuse std::path::Path;\nuse s"
  },
  {
    "path": "crates/volta-core/src/run/node.rs",
    "chars": 1341,
    "preview": "use std::env;\nuse std::ffi::OsString;\n\nuse super::executor::{Executor, ToolCommand, ToolKind};\nuse super::{debug_active_"
  },
  {
    "path": "crates/volta-core/src/run/npm.rs",
    "chars": 3802,
    "preview": "use std::env;\nuse std::ffi::OsString;\nuse std::fs::File;\n\nuse super::executor::{Executor, ToolCommand, ToolKind, Uninsta"
  },
  {
    "path": "crates/volta-core/src/run/npx.rs",
    "chars": 1992,
    "preview": "use std::env;\nuse std::ffi::OsString;\n\nuse super::executor::{Executor, ToolCommand, ToolKind};\nuse super::{debug_active_"
  },
  {
    "path": "crates/volta-core/src/run/parser.rs",
    "chars": 38464,
    "preview": "use std::env;\nuse std::ffi::OsStr;\nuse std::iter::once;\n\nuse super::executor::{\n    Executor, InternalInstallCommand, Pa"
  },
  {
    "path": "crates/volta-core/src/run/pnpm.rs",
    "chars": 2346,
    "preview": "use std::env;\nuse std::ffi::OsString;\n\nuse super::executor::{Executor, ToolCommand, ToolKind};\nuse super::{debug_active_"
  },
  {
    "path": "crates/volta-core/src/run/yarn.rs",
    "chars": 2583,
    "preview": "use std::env;\nuse std::ffi::OsString;\n\nuse super::executor::{Executor, ToolCommand, ToolKind};\nuse super::parser::Comman"
  },
  {
    "path": "crates/volta-core/src/session.rs",
    "chars": 6739,
    "preview": "//! Provides the `Session` type, which represents the user's state during an\n//! execution of a Volta tool, including th"
  },
  {
    "path": "crates/volta-core/src/shim.rs",
    "chars": 6137,
    "preview": "//! Provides utilities for modifying shims for 3rd-party executables\n\nuse std::collections::HashSet;\nuse std::fs;\nuse st"
  },
  {
    "path": "crates/volta-core/src/signal.rs",
    "chars": 585,
    "preview": "use std::process::exit;\nuse std::sync::atomic::{AtomicBool, Ordering};\n\nuse log::debug;\n\nstatic SHIM_HAS_CONTROL: Atomic"
  },
  {
    "path": "crates/volta-core/src/style.rs",
    "chars": 4272,
    "preview": "//! The view layer of Volta, with utilities for styling command-line output.\nuse std::borrow::Cow;\nuse std::error::Error"
  },
  {
    "path": "crates/volta-core/src/sync.rs",
    "chars": 4909,
    "preview": "//! Inter-process locking on the Volta directory\n//!\n//! To avoid issues where multiple separate invocations of Volta mo"
  },
  {
    "path": "crates/volta-core/src/tool/mod.rs",
    "chars": 10197,
    "preview": "use std::env;\nuse std::fmt::{self, Display};\nuse std::path::PathBuf;\n\nuse crate::error::{ErrorKind, Fallible};\nuse crate"
  },
  {
    "path": "crates/volta-core/src/tool/node/fetch.rs",
    "chars": 7364,
    "preview": "//! Provides fetcher for Node distributions\n\nuse std::fs::{read_to_string, write, File};\nuse std::path::{Path, PathBuf};"
  },
  {
    "path": "crates/volta-core/src/tool/node/metadata.rs",
    "chars": 2619,
    "preview": "use std::collections::HashSet;\n\nuse super::NODE_DISTRO_IDENTIFIER;\n#[cfg(any(\n    all(target_os = \"macos\", target_arch ="
  },
  {
    "path": "crates/volta-core/src/tool/node/mod.rs",
    "chars": 14266,
    "preview": "use std::fmt::{self, Display};\n\nuse super::{\n    check_fetched, check_shim_reachable, debug_already_fetched, info_fetche"
  },
  {
    "path": "crates/volta-core/src/tool/node/resolve.rs",
    "chars": 9511,
    "preview": "//! Provides resolution of Node requirements into specific versions, using the NodeJS index\n\nuse std::fs::File;\nuse std:"
  },
  {
    "path": "crates/volta-core/src/tool/npm/fetch.rs",
    "chars": 5922,
    "preview": "//! Provides fetcher for npm distributions\n\nuse std::fs::{write, File};\nuse std::path::Path;\n\nuse super::super::download"
  },
  {
    "path": "crates/volta-core/src/tool/npm/mod.rs",
    "chars": 5659,
    "preview": "use std::fmt::{self, Display};\n\nuse super::node::load_default_npm_version;\nuse super::{\n    check_fetched, check_shim_re"
  },
  {
    "path": "crates/volta-core/src/tool/npm/resolve.rs",
    "chars": 2512,
    "preview": "//! Provides resolution of npm Version requirements into specific versions\n\nuse super::super::registry::{\n    fetch_npm_"
  },
  {
    "path": "crates/volta-core/src/tool/package/configure.rs",
    "chars": 2797,
    "preview": "use std::path::PathBuf;\n\nuse super::manager::PackageManager;\nuse super::metadata::{BinConfig, PackageConfig, PackageMani"
  },
  {
    "path": "crates/volta-core/src/tool/package/install.rs",
    "chars": 1951,
    "preview": "use std::path::PathBuf;\n\nuse super::manager::PackageManager;\nuse crate::command::create_command;\nuse crate::error::{Cont"
  },
  {
    "path": "crates/volta-core/src/tool/package/manager.rs",
    "chars": 9066,
    "preview": "use std::ffi::OsStr;\nuse std::fs::File;\nuse std::path::{Path, PathBuf};\nuse std::process::Command;\n\nuse super::metadata:"
  },
  {
    "path": "crates/volta-core/src/tool/package/metadata.rs",
    "chars": 10862,
    "preview": "use std::collections::HashMap;\nuse std::fs::File;\nuse std::io;\nuse std::path::Path;\n\nuse super::manager::PackageManager;"
  },
  {
    "path": "crates/volta-core/src/tool/package/mod.rs",
    "chars": 10455,
    "preview": "use std::fmt::{self, Display};\nuse std::fs::create_dir_all;\nuse std::path::{Path, PathBuf};\nuse std::process::Command;\n\n"
  },
  {
    "path": "crates/volta-core/src/tool/package/uninstall.rs",
    "chars": 3841,
    "preview": "use super::metadata::{BinConfig, PackageConfig};\nuse crate::error::{Context, ErrorKind, Fallible};\nuse crate::fs::{\n    "
  },
  {
    "path": "crates/volta-core/src/tool/pnpm/fetch.rs",
    "chars": 5751,
    "preview": "//! Provides fetcher for pnpm distributions\n\nuse std::fs::{write, File};\nuse std::path::Path;\n\nuse archive::{Archive, Ta"
  },
  {
    "path": "crates/volta-core/src/tool/pnpm/mod.rs",
    "chars": 3029,
    "preview": "use node_semver::Version;\nuse std::fmt::{self, Display};\n\nuse crate::error::{ErrorKind, Fallible};\nuse crate::inventory:"
  },
  {
    "path": "crates/volta-core/src/tool/pnpm/resolve.rs",
    "chars": 2367,
    "preview": "use log::debug;\nuse node_semver::{Range, Version};\n\nuse crate::error::{ErrorKind, Fallible};\nuse crate::hook::ToolHooks;"
  },
  {
    "path": "crates/volta-core/src/tool/registry.rs",
    "chars": 4762,
    "preview": "use std::collections::HashMap;\nuse std::path::{Path, PathBuf};\n\nuse super::registry_fetch_error;\nuse crate::error::{Cont"
  },
  {
    "path": "crates/volta-core/src/tool/serial.rs",
    "chars": 18548,
    "preview": "use std::cmp::Ordering;\n\nuse super::Spec;\nuse crate::error::{ErrorKind, Fallible};\nuse crate::version::{VersionSpec, Ver"
  },
  {
    "path": "crates/volta-core/src/tool/yarn/fetch.rs",
    "chars": 5243,
    "preview": "//! Provides fetcher for Yarn distributions\n\nuse std::fs::File;\nuse std::path::Path;\n\nuse super::super::download_tool_er"
  },
  {
    "path": "crates/volta-core/src/tool/yarn/metadata.rs",
    "chars": 1569,
    "preview": "use std::collections::BTreeSet;\n\nuse crate::version::version_serde;\nuse node_semver::Version;\nuse serde::Deserialize;\n\n/"
  },
  {
    "path": "crates/volta-core/src/tool/yarn/mod.rs",
    "chars": 3049,
    "preview": "use std::fmt::{self, Display};\n\nuse super::{\n    check_fetched, check_shim_reachable, debug_already_fetched, info_fetche"
  },
  {
    "path": "crates/volta-core/src/tool/yarn/resolve.rs",
    "chars": 8033,
    "preview": "//! Provides resolution of Yarn requirements into specific versions\n\nuse super::super::registry::{\n    fetch_npm_registr"
  },
  {
    "path": "crates/volta-core/src/toolchain/mod.rs",
    "chars": 4481,
    "preview": "use std::fs::write;\n\nuse crate::error::{Context, ErrorKind, Fallible};\nuse crate::fs::touch;\nuse crate::layout::volta_ho"
  },
  {
    "path": "crates/volta-core/src/toolchain/serial.rs",
    "chars": 4120,
    "preview": "use crate::error::{Context, ErrorKind, Fallible, VoltaError};\nuse crate::platform::PlatformSpec;\nuse crate::version::{op"
  },
  {
    "path": "crates/volta-core/src/version/mod.rs",
    "chars": 5381,
    "preview": "use std::fmt;\nuse std::str::FromStr;\n\nuse crate::error::{Context, ErrorKind, Fallible, VoltaError};\nuse node_semver::{Ra"
  },
  {
    "path": "crates/volta-core/src/version/serial.rs",
    "chars": 1777,
    "preview": "use node_semver::{Range, SemverError};\n\n// NOTE: using `parse_compat` here because the semver crate defaults to\n// parsi"
  },
  {
    "path": "crates/volta-layout/Cargo.toml",
    "chars": 191,
    "preview": "[package]\nname = \"volta-layout\"\nversion = \"0.1.1\"\nauthors = [\"Chuck Pierce <cpierce.grad@gmail.com>\"]\nedition = \"2021\"\n\n"
  },
  {
    "path": "crates/volta-layout/src/lib.rs",
    "chars": 183,
    "preview": "#[macro_use]\nmod macros;\n\npub mod v0;\npub mod v1;\npub mod v2;\npub mod v3;\npub mod v4;\n\nfn executable(name: &str) -> Stri"
  },
  {
    "path": "crates/volta-layout/src/macros.rs",
    "chars": 203,
    "preview": "macro_rules! path_buf {\n    ($base:expr, $( $x:expr ), *) => {\n        {\n            let mut temp = $base;\n            $"
  },
  {
    "path": "crates/volta-layout/src/v0.rs",
    "chars": 3421,
    "preview": "use std::path::PathBuf;\n\nuse super::executable;\nuse volta_layout_macro::layout;\n\nlayout! {\n    pub struct VoltaInstall {"
  },
  {
    "path": "crates/volta-layout/src/v1.rs",
    "chars": 3424,
    "preview": "use std::path::PathBuf;\n\nuse super::executable;\nuse volta_layout_macro::layout;\n\nlayout! {\n    pub struct VoltaInstall {"
  },
  {
    "path": "crates/volta-layout/src/v2.rs",
    "chars": 3562,
    "preview": "use std::path::PathBuf;\n\nuse super::executable;\nuse volta_layout_macro::layout;\n\npub use crate::v1::VoltaInstall;\n\nlayou"
  },
  {
    "path": "crates/volta-layout/src/v3.rs",
    "chars": 3575,
    "preview": "use std::path::PathBuf;\n\nuse super::executable;\nuse volta_layout_macro::layout;\n\npub use crate::v1::VoltaInstall;\n\nlayou"
  },
  {
    "path": "crates/volta-layout/src/v4.rs",
    "chars": 3763,
    "preview": "use std::path::PathBuf;\n\nuse volta_layout_macro::layout;\n\npub use crate::v1::VoltaInstall;\n\nlayout! {\n    pub struct Vol"
  },
  {
    "path": "crates/volta-layout-macro/Cargo.toml",
    "chars": 218,
    "preview": "[package]\nname = \"volta-layout-macro\"\nversion = \"0.1.0\"\nauthors = [\"David Herman <david.herman@gmail.com>\"]\nedition = \"2"
  },
  {
    "path": "crates/volta-layout-macro/src/ast.rs",
    "chars": 9233,
    "preview": "use crate::ir::{Entry, Ir};\nuse proc_macro2::TokenStream;\nuse std::collections::HashMap;\nuse syn::parse::{self, Parse, P"
  },
  {
    "path": "crates/volta-layout-macro/src/ir.rs",
    "chars": 6762,
    "preview": "// The `proc_macro2` crate is a polyfill for advanced functionality of Rust's\n// procedural macros, not all of which hav"
  },
  {
    "path": "crates/volta-layout-macro/src/lib.rs",
    "chars": 1036,
    "preview": "#![recursion_limit = \"128\"]\n\nextern crate proc_macro;\n\nmod ast;\nmod ir;\n\nuse crate::ast::Ast;\nuse proc_macro::TokenStrea"
  },
  {
    "path": "crates/volta-migrate/Cargo.toml",
    "chars": 447,
    "preview": "[package]\nname = \"volta-migrate\"\nversion = \"0.1.0\"\nauthors = [\"Charles Pierce <cpierce.grad@gmail.com>\"]\nedition = \"2021"
  },
  {
    "path": "crates/volta-migrate/src/empty.rs",
    "chars": 385,
    "preview": "use std::path::PathBuf;\n\n/// Represents an Empty (or uninitialized) Volta layout, one that has never been used by any pr"
  },
  {
    "path": "crates/volta-migrate/src/lib.rs",
    "chars": 6735,
    "preview": "//! Provides types for modeling the current state of the Volta directory and for migrating between versions\n//!\n//! A ne"
  },
  {
    "path": "crates/volta-migrate/src/v0.rs",
    "chars": 432,
    "preview": "use std::path::PathBuf;\n\nuse volta_layout::v0::VoltaHome;\n\n/// Represents a V0 Volta layout (from before v0.7.0)\n///\n///"
  },
  {
    "path": "crates/volta-migrate/src/v1.rs",
    "chars": 2987,
    "preview": "#[cfg(unix)]\nuse std::fs::remove_file;\nuse std::fs::File;\nuse std::path::PathBuf;\n\nuse super::empty::Empty;\nuse super::v"
  },
  {
    "path": "crates/volta-migrate/src/v2.rs",
    "chars": 6588,
    "preview": "use std::fs::{read_to_string, write, File};\nuse std::io;\nuse std::path::{Path, PathBuf};\n\nuse super::empty::Empty;\nuse s"
  },
  {
    "path": "crates/volta-migrate/src/v3/config.rs",
    "chars": 1295,
    "preview": "use std::fs::File;\nuse std::path::Path;\n\nuse node_semver::Version;\nuse volta_core::platform::PlatformSpec;\nuse volta_cor"
  },
  {
    "path": "crates/volta-migrate/src/v3.rs",
    "chars": 5750,
    "preview": "use std::fs::File;\nuse std::path::{Path, PathBuf};\n\nuse crate::empty::Empty;\nuse crate::v2::V2;\nuse log::{debug, warn};\n"
  },
  {
    "path": "crates/volta-migrate/src/v4.rs",
    "chars": 5126,
    "preview": "use std::fs::File;\r\nuse std::path::PathBuf;\r\n\r\nuse super::empty::Empty;\r\nuse super::v3::V3;\r\nuse log::debug;\r\nuse volta_"
  },
  {
    "path": "dev/package.json",
    "chars": 292,
    "preview": "{\n  \"name\": \"example\",\n  \"version\": \"1.0\",\n  \"description\": \"an example Node project using volta\",\n  \"author\": \"Dave Her"
  },
  {
    "path": "dev/rpm/build-rpm.sh",
    "chars": 1756,
    "preview": "#!/usr/bin/env bash\n# Build an RPM package for Volta\n\n# using the directions from https://rpm-packaging-guide.github.io/"
  },
  {
    "path": "dev/rpm/volta.spec",
    "chars": 2559,
    "preview": "Name:           volta\nVersion:        0.8.2\nRelease:        1%{?dist}\nSummary:        The JavaScript Launcher ⚡\n\nLicense"
  },
  {
    "path": "dev/unix/SHASUMS256.txt",
    "chars": 83,
    "preview": "fbdc4b8cb33fb6d19e5f07b22423265943d34e7e5c3d5a1efcecc9621854f9cb  volta-install.sh\n"
  },
  {
    "path": "dev/unix/boot-install.sh",
    "chars": 4520,
    "preview": "#!/usr/bin/env bash\n\n# This is the bootstrap Unix installer served by `https://get.volta.sh`.\n# Its responsibility is to"
  },
  {
    "path": "dev/unix/build.sh",
    "chars": 1780,
    "preview": "#!/usr/bin/env bash\n\nscript_dir=\"$(dirname \"$0\")\"\n\nusage() {\n  cat <<END_USAGE\nbuild.sh: generate volta's generic unix i"
  },
  {
    "path": "dev/unix/install.sh.in",
    "chars": 7165,
    "preview": "#!/usr/bin/env bash\n\n{\n\nvolta_unpack_volta() {\n  base64 --decode <<'END_BINARY_PAYLOAD'\n<PLACEHOLDER_VOLTA_PAYLOAD>\nEND_"
  },
  {
    "path": "dev/unix/release.sh",
    "chars": 2306,
    "preview": "#!/usr/bin/env bash\n\n# Script to build the binaries and package them up for release.\n# This should be run from the top-l"
  },
  {
    "path": "dev/unix/test-events",
    "chars": 439,
    "preview": "#!/usr/bin/env bash\n\n# long-running script to show events and test spawning processes\n\nmy_pid=\"$$\"\n\necho \"$my_pid called"
  },
  {
    "path": "dev/unix/tests/install-script.bats",
    "chars": 2590,
    "preview": "# test the volta-install.sh script\n\n# load the functions from the script\nsource dev/unix/volta-install.sh\n\n\n# happy path"
  },
  {
    "path": "dev/unix/volta-install-legacy.sh",
    "chars": 14618,
    "preview": "#!/usr/bin/env bash\n\n# This is the bootstrap Unix installer served by `https://get.volta.sh`.\n# Its responsibility is to"
  },
  {
    "path": "dev/unix/volta-install.sh",
    "chars": 10460,
    "preview": "#!/usr/bin/env bash\n\n# This is the bootstrap Unix installer served by `https://get.volta.sh`.\n# Its responsibility is to"
  },
  {
    "path": "rust-toolchain.toml",
    "chars": 84,
    "preview": "[toolchain]\nchannel = \"1.75\"\ncomponents = [\"clippy\", \"rustfmt\"]\nprofile = \"minimal\"\n"
  },
  {
    "path": "src/cli.rs",
    "chars": 4418,
    "preview": "use clap::{builder::styling, ColorChoice, Parser};\n\nuse crate::command::{self, Command};\nuse volta_core::error::{ExitCod"
  },
  {
    "path": "src/command/completions.rs",
    "chars": 2606,
    "preview": "use std::path::PathBuf;\n\nuse clap::CommandFactory;\nuse clap_complete::Shell;\nuse log::info;\n\nuse volta_core::{\n    error"
  },
  {
    "path": "src/command/fetch.rs",
    "chars": 746,
    "preview": "use volta_core::error::{ExitCode, Fallible};\nuse volta_core::session::{ActivityKind, Session};\nuse volta_core::tool;\n\nus"
  },
  {
    "path": "src/command/install.rs",
    "chars": 760,
    "preview": "use volta_core::error::{ExitCode, Fallible};\nuse volta_core::session::{ActivityKind, Session};\nuse volta_core::tool::Spe"
  },
  {
    "path": "src/command/list/human.rs",
    "chars": 51909,
    "preview": "//! Define the \"human\" format style for list commands.\n\nuse std::collections::BTreeMap;\n\nuse super::{Node, Package, Pack"
  },
  {
    "path": "src/command/list/mod.rs",
    "chars": 8779,
    "preview": "mod human;\nmod plain;\nmod toolchain;\n\nuse std::io::IsTerminal as _;\nuse std::{fmt, path::PathBuf, str::FromStr};\n\nuse no"
  },
  {
    "path": "src/command/list/plain.rs",
    "chars": 18768,
    "preview": "//! Define the \"plain\" format style for list commands.\n\nuse node_semver::Version;\n\nuse volta_core::style::tool_version;\n"
  },
  {
    "path": "src/command/list/toolchain.rs",
    "chars": 13817,
    "preview": "use super::{Filter, Node, Package, PackageManager, Source};\nuse crate::command::list::PackageManagerKind;\nuse node_semve"
  },
  {
    "path": "src/command/mod.rs",
    "chars": 937,
    "preview": "pub(crate) mod completions;\npub(crate) mod fetch;\npub(crate) mod install;\npub(crate) mod list;\npub(crate) mod pin;\npub(c"
  },
  {
    "path": "src/command/pin.rs",
    "chars": 711,
    "preview": "use volta_core::error::{ExitCode, Fallible};\nuse volta_core::session::{ActivityKind, Session};\nuse volta_core::tool::Spe"
  },
  {
    "path": "src/command/run.rs",
    "chars": 5277,
    "preview": "use std::collections::HashMap;\nuse std::ffi::OsString;\n\nuse crate::command::Command;\nuse crate::common::{Error, IntoResu"
  },
  {
    "path": "src/command/setup.rs",
    "chars": 8953,
    "preview": "use log::info;\nuse volta_core::error::{ExitCode, Fallible};\nuse volta_core::layout::volta_home;\nuse volta_core::session:"
  },
  {
    "path": "src/command/uninstall.rs",
    "chars": 1310,
    "preview": "use volta_core::error::{ErrorKind, ExitCode, Fallible};\nuse volta_core::session::{ActivityKind, Session};\nuse volta_core"
  },
  {
    "path": "src/command/use.rs",
    "chars": 1216,
    "preview": "use crate::command::Command;\nuse volta_core::error::{ErrorKind, ExitCode, Fallible};\nuse volta_core::session::{ActivityK"
  },
  {
    "path": "src/command/which.rs",
    "chars": 2716,
    "preview": "use std::env;\nuse std::ffi::OsString;\n\nuse which::which_in;\n\nuse volta_core::error::{Context, ErrorKind, ExitCode, Falli"
  },
  {
    "path": "src/common.rs",
    "chars": 1184,
    "preview": "use std::process::{Command, ExitStatus};\n\nuse volta_core::error::{Context, ErrorKind, VoltaError};\nuse volta_core::layou"
  },
  {
    "path": "src/main.rs",
    "chars": 1780,
    "preview": "#[macro_use]\nmod command;\nmod cli;\n\nuse clap::Parser;\n\nuse volta_core::error::report_error;\nuse volta_core::log::{LogCon"
  },
  {
    "path": "src/volta-migrate.rs",
    "chars": 979,
    "preview": "use volta_core::error::{report_error, ExitCode};\nuse volta_core::layout::volta_home;\nuse volta_core::log::{LogContext, L"
  },
  {
    "path": "src/volta-shim.rs",
    "chars": 1263,
    "preview": "mod common;\n\nuse common::{ensure_layout, Error, IntoResult};\nuse volta_core::error::{report_error, ExitCode};\nuse volta_"
  },
  {
    "path": "tests/acceptance/corrupted_download.rs",
    "chars": 5219,
    "preview": "use crate::support::sandbox::{sandbox, DistroMetadata, NodeFixture, PnpmFixture, Yarn1Fixture};\nuse hamcrest2::assert_th"
  },
  {
    "path": "tests/acceptance/direct_install.rs",
    "chars": 13747,
    "preview": "use crate::support::sandbox::{sandbox, DistroMetadata, NodeFixture, NpmFixture, Yarn1Fixture};\nuse hamcrest2::assert_tha"
  },
  {
    "path": "tests/acceptance/direct_uninstall.rs",
    "chars": 10549,
    "preview": "//! Tests for `npm uninstall`, `npm uninstall --global`, `yarn remove`, and\n//! `yarn global remove`, which we support a"
  },
  {
    "path": "tests/acceptance/execute_binary.rs",
    "chars": 9888,
    "preview": "use std::path::PathBuf;\n\nuse crate::support::sandbox::{sandbox, PackageBinInfo};\nuse cfg_if::cfg_if;\nuse hamcrest2::asse"
  },
  {
    "path": "tests/acceptance/hooks.rs",
    "chars": 15505,
    "preview": "use std::path::PathBuf;\nuse std::{thread, time};\n\nuse crate::support::events_helpers::{\n    assert_events, match_args, m"
  },
  {
    "path": "tests/acceptance/main.rs",
    "chars": 502,
    "preview": "use cfg_if::cfg_if;\n\ncfg_if! {\n    if #[cfg(feature = \"mock-network\")] {\n        mod support;\n\n        // test files\n   "
  },
  {
    "path": "tests/acceptance/merged_platform.rs",
    "chars": 13762,
    "preview": "use std::{thread, time};\n\nuse crate::support::events_helpers::{assert_events, match_args, match_start, match_tool_end};\n"
  },
  {
    "path": "tests/acceptance/migrations.rs",
    "chars": 8185,
    "preview": "use crate::support::sandbox::{sandbox, Sandbox};\nuse hamcrest2::assert_that;\nuse hamcrest2::prelude::*;\nuse test_support"
  },
  {
    "path": "tests/acceptance/run_shim_directly.rs",
    "chars": 477,
    "preview": "use crate::support::sandbox::{sandbox, shim_exe};\nuse hamcrest2::assert_that;\nuse hamcrest2::prelude::*;\nuse test_suppor"
  },
  {
    "path": "tests/acceptance/support/events_helpers.rs",
    "chars": 3761,
    "preview": "use std::fs::File;\n\nuse crate::support::sandbox::Sandbox;\nuse hamcrest2::assert_that;\nuse hamcrest2::prelude::*;\n\nuse vo"
  },
  {
    "path": "tests/acceptance/support/mod.rs",
    "chars": 41,
    "preview": "pub mod events_helpers;\npub mod sandbox;\n"
  },
  {
    "path": "tests/acceptance/support/sandbox.rs",
    "chars": 30913,
    "preview": "use std::env;\nuse std::ffi::{OsStr, OsString};\nuse std::fs::{self, File};\nuse std::io::{Read, Write};\nuse std::path::{Pa"
  },
  {
    "path": "tests/acceptance/verbose_errors.rs",
    "chars": 4328,
    "preview": "use crate::support::sandbox::sandbox;\nuse ci_info::types::{CiInfo, Vendor};\nuse hamcrest2::assert_that;\nuse hamcrest2::p"
  },
  {
    "path": "tests/acceptance/volta_bypass.rs",
    "chars": 883,
    "preview": "use crate::support::sandbox::{sandbox, shim_exe};\nuse hamcrest2::assert_that;\nuse hamcrest2::prelude::*;\nuse test_suppor"
  },
  {
    "path": "tests/acceptance/volta_install.rs",
    "chars": 12240,
    "preview": "use crate::support::sandbox::{\n    sandbox, DistroMetadata, NodeFixture, NpmFixture, PnpmFixture, Sandbox, Yarn1Fixture,"
  },
  {
    "path": "tests/acceptance/volta_pin.rs",
    "chars": 30644,
    "preview": "use crate::support::sandbox::{\n    sandbox, DistroMetadata, NodeFixture, NpmFixture, PnpmFixture, Yarn1Fixture, YarnBerr"
  },
  {
    "path": "tests/acceptance/volta_run.rs",
    "chars": 16275,
    "preview": "use crate::support::sandbox::{\n    sandbox, DistroMetadata, NodeFixture, NpmFixture, PnpmFixture, Yarn1Fixture, YarnBerr"
  },
  {
    "path": "tests/acceptance/volta_uninstall.rs",
    "chars": 6735,
    "preview": "//! Tests for `volta uninstall`.\n\nuse crate::support::sandbox::{sandbox, Sandbox};\nuse hamcrest2::assert_that;\nuse hamcr"
  },
  {
    "path": "tests/fixtures/pnpm-0.0.1.tgz",
    "chars": 10,
    "preview": "CORRUPTED\n"
  },
  {
    "path": "tests/fixtures/yarn-0.0.1.tgz",
    "chars": 10,
    "preview": "CORRUPTED\n"
  },
  {
    "path": "tests/smoke/autodownload.rs",
    "chars": 1781,
    "preview": "use crate::support::temp_project::temp_project;\n\nuse hamcrest2::assert_that;\nuse hamcrest2::prelude::*;\nuse test_support"
  },
  {
    "path": "tests/smoke/direct_install.rs",
    "chars": 2648,
    "preview": "use crate::support::temp_project::temp_project;\nuse hamcrest2::assert_that;\nuse hamcrest2::prelude::*;\nuse test_support:"
  },
  {
    "path": "tests/smoke/direct_upgrade.rs",
    "chars": 3088,
    "preview": "use crate::support::temp_project::temp_project;\nuse hamcrest2::assert_that;\nuse hamcrest2::prelude::*;\nuse test_support:"
  }
]

// ... and 26 more files (download for full content)

About this extraction

This page contains the full source code of the volta-cli/volta GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 226 files (1008.4 KB), approximately 252.7k tokens, and a symbol index with 1680 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.

Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.

Copied to clipboard!